summaryrefslogtreecommitdiff
path: root/source/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp16
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp21
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp21
-rw-r--r--source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp4
-rw-r--r--source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp29
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp4
-rw-r--r--source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp51
-rw-r--r--source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp8
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp33
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp45
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp1217
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h2
-rw-r--r--source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp21
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp54
-rw-r--r--source/Plugins/Architecture/Arm/ArchitectureArm.cpp69
-rw-r--r--source/Plugins/Architecture/Arm/ArchitectureArm.h2
-rw-r--r--source/Plugins/Architecture/CMakeLists.txt1
-rw-r--r--source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp69
-rw-r--r--source/Plugins/Architecture/PPC64/ArchitecturePPC64.h44
-rw-r--r--source/Plugins/Architecture/PPC64/CMakeLists.txt11
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp312
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h60
-rw-r--r--source/Plugins/DynamicLoader/CMakeLists.txt5
-rw-r--r--source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp296
-rw-r--r--source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h6
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp38
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp20
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h19
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp173
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp62
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp220
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h13
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp36
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h17
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp204
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h19
-rw-r--r--source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp18
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp12
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h31
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h25
-rw-r--r--source/Plugins/ExpressionParser/Clang/CMakeLists.txt2
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp62
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangASTSource.h66
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp97
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h81
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp82
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h16
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h42
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp6
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h12
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangHost.cpp142
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangHost.h26
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp38
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp9
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h18
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp164
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUserExpression.h22
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h12
-rw-r--r--source/Plugins/ExpressionParser/Clang/IRForTarget.cpp62
-rw-r--r--source/Plugins/ExpressionParser/Clang/IRForTarget.h105
-rw-r--r--source/Plugins/ExpressionParser/Go/GoParser.cpp10
-rw-r--r--source/Plugins/ExpressionParser/Go/GoUserExpression.cpp20
-rw-r--r--source/Plugins/ExpressionParser/Go/GoUserExpression.h14
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp566
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp28
-rw-r--r--source/Plugins/Instruction/CMakeLists.txt1
-rw-r--r--source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp23
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp11
-rw-r--r--source/Plugins/Instruction/PPC64/CMakeLists.txt11
-rw-r--r--source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp406
-rw-r--r--source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h97
-rw-r--r--source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp4
-rw-r--r--source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp7
-rw-r--r--source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp4
-rw-r--r--source/Plugins/JITLoader/GDB/CMakeLists.txt2
-rw-r--r--source/Plugins/Language/CPlusPlus/BlockPointer.cpp5
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp46
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp36
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxx.cpp14
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxList.cpp8
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxMap.cpp4
-rw-r--r--source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp29
-rw-r--r--source/Plugins/Language/ObjC/Cocoa.cpp119
-rw-r--r--source/Plugins/Language/ObjC/Cocoa.h3
-rw-r--r--source/Plugins/Language/ObjC/NSDictionary.cpp24
-rw-r--r--source/Plugins/Language/ObjC/NSError.cpp11
-rw-r--r--source/Plugins/Language/ObjC/NSException.cpp11
-rw-r--r--source/Plugins/Language/ObjC/NSSet.cpp33
-rw-r--r--source/Plugins/Language/ObjC/NSString.cpp7
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.cpp23
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp78
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp3
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp38
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp16
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h2
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp198
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h3
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp545
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp54
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp14
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp34
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp207
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp2
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp68
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp45
-rw-r--r--source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp11
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.cpp7
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.h39
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp560
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h21
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp13
-rw-r--r--source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp1988
-rw-r--r--source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h25
-rw-r--r--source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp18
-rw-r--r--source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp7
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp90
-rw-r--r--source/Plugins/Platform/Android/AdbClient.cpp4
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroid.cpp29
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp13
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp37
-rw-r--r--source/Plugins/Platform/Linux/PlatformLinux.cpp35
-rw-r--r--source/Plugins/Platform/MacOSX/CMakeLists.txt4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp16
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp33
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp33
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwin.cpp299
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwin.h9
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp154
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp19
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp8
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp107
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp41
-rw-r--r--source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt17
-rw-r--r--source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h (renamed from source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h)2
-rw-r--r--source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm (renamed from source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm)25
-rw-r--r--source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp136
-rw-r--r--source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp20
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp489
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h13
-rw-r--r--source/Plugins/Platform/Windows/PlatformWindows.cpp76
-rw-r--r--source/Plugins/Platform/Windows/PlatformWindows.h2
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp45
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h5
-rw-r--r--source/Plugins/Process/CMakeLists.txt2
-rw-r--r--source/Plugins/Process/Darwin/CFString.cpp11
-rw-r--r--source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp58
-rw-r--r--source/Plugins/Process/Darwin/MachException.cpp35
-rw-r--r--source/Plugins/Process/Darwin/NativeProcessDarwin.cpp163
-rw-r--r--source/Plugins/Process/Darwin/NativeProcessDarwin.h22
-rw-r--r--source/Plugins/Process/Darwin/NativeThreadDarwin.cpp54
-rw-r--r--source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp69
-rw-r--r--source/Plugins/Process/FreeBSD/CMakeLists.txt4
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.cpp69
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.h2
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXStopInfo.h6
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp35
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp138
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h23
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h4
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp8
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp6
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp32
-rw-r--r--source/Plugins/Process/Linux/CMakeLists.txt4
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.cpp384
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.h20
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp44
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h4
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp21
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h4
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp9
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp17
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h4
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp10
-rwxr-xr-xsource/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp42
-rw-r--r--source/Plugins/Process/Linux/NativeThreadLinux.cpp8
-rw-r--r--source/Plugins/Process/Linux/ProcessorTrace.h2
-rw-r--r--source/Plugins/Process/Linux/SingleStepCheck.cpp6
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp67
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp57
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp18
-rw-r--r--source/Plugins/Process/NetBSD/CMakeLists.txt4
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp61
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.h6
-rw-r--r--source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp17
-rw-r--r--source/Plugins/Process/POSIX/CMakeLists.txt3
-rw-r--r--source/Plugins/Process/POSIX/CrashReason.cpp3
-rw-r--r--source/Plugins/Process/Utility/CMakeLists.txt3
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp94
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.h23
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.h6
-rw-r--r--source/Plugins/Process/Utility/InstructionUtils.h3
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwinConstants.h26
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp21
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp25
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp24
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp12
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp329
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp14
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMemory.cpp6
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp15
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp15
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp17
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp15
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp14
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp8
-rw-r--r--source/Plugins/Process/Utility/RegisterInfoInterface.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_ppc64.h331
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.cpp57
-rw-r--r--source/Plugins/Process/Utility/ThreadMemory.cpp2
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp147
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.h1
-rw-r--r--source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp8
-rw-r--r--source/Plugins/Process/Utility/lldb-ppc64-register-enums.h139
-rw-r--r--source/Plugins/Process/Windows/Common/CMakeLists.txt3
-rw-r--r--source/Plugins/Process/Windows/Common/DebuggerThread.cpp62
-rw-r--r--source/Plugins/Process/Windows/Common/ProcessWindows.cpp196
-rw-r--r--source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp76
-rw-r--r--source/Plugins/Process/Windows/Common/TargetThreadWindows.h7
-rw-r--r--source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp61
-rw-r--r--source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp29
-rw-r--r--source/Plugins/Process/elf-core/CMakeLists.txt2
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp55
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp4
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp31
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp59
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h5
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp203
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h9
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp322
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h21
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp85
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp116
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp55
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp140
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp784
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h17
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp46
-rw-r--r--source/Plugins/Process/mach-core/CMakeLists.txt2
-rw-r--r--source/Plugins/Process/mach-core/ProcessMachCore.cpp136
-rw-r--r--source/Plugins/Process/mach-core/ThreadMachCore.cpp12
-rw-r--r--source/Plugins/Process/minidump/CMakeLists.txt2
-rw-r--r--source/Plugins/Process/minidump/MinidumpParser.cpp206
-rw-r--r--source/Plugins/Process/minidump/MinidumpParser.h14
-rw-r--r--source/Plugins/Process/minidump/MinidumpTypes.cpp46
-rw-r--r--source/Plugins/Process/minidump/MinidumpTypes.h15
-rw-r--r--source/Plugins/Process/minidump/ProcessMinidump.cpp102
-rw-r--r--source/Plugins/Process/minidump/ProcessMinidump.h2
-rw-r--r--source/Plugins/ScriptInterpreter/CMakeLists.txt4
-rw-r--r--source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp2
-rw-r--r--source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h2
-rw-r--r--source/Plugins/ScriptInterpreter/Python/CMakeLists.txt13
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp124
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp31
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp569
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h25
-rw-r--r--source/Plugins/ScriptInterpreter/Python/lldb-python.h5
-rw-r--r--source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp291
-rw-r--r--source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp177
-rw-r--r--source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h64
-rw-r--r--source/Plugins/SymbolFile/DWARF/CMakeLists.txt8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DIERef.cpp11
-rw-r--r--source/Plugins/SymbolFile/DWARF/DIERef.h12
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp911
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp55
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp7
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h1
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp1
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp9
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.h8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp193
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h157
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp1058
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h227
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp205
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIE.h173
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp10
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp57
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp300
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h25
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp266
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h70
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp245
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h5
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp255
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h40
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp146
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h95
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp10
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDefines.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp20
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.h12
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp68
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFIndex.h69
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp755
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFUnit.h252
-rw-r--r--source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp272
-rw-r--r--source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h83
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp116
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h26
-rw-r--r--source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp488
-rw-r--r--source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h75
-rw-r--r--source/Plugins/SymbolFile/DWARF/NameToDIE.cpp1
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp1442
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h89
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp149
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h10
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp12
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h14
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp5
-rw-r--r--source/Plugins/SymbolFile/PDB/CMakeLists.txt1
-rw-r--r--source/Plugins/SymbolFile/PDB/PDBASTParser.cpp341
-rw-r--r--source/Plugins/SymbolFile/PDB/PDBASTParser.h10
-rw-r--r--source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp585
-rw-r--r--source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h45
-rw-r--r--source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp1277
-rw-r--r--source/Plugins/SymbolFile/PDB/SymbolFilePDB.h65
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp30
-rw-r--r--source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp16
-rw-r--r--source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp83
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp27
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp22
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp27
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp24
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp73
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp67
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp29
-rw-r--r--source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp126
349 files changed, 16776 insertions, 13510 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 1bd1c1bf8dd4..e0e293d7ae68 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -1466,8 +1466,8 @@ bool ABIMacOSX_arm::GetArgumentValues(Thread &thread, ValueList &values) const {
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
@@ -1589,10 +1589,8 @@ ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl(
case 128:
if (IsArmv7kProcess()) {
// "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"
+ // 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);
@@ -1756,10 +1754,8 @@ Status ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
}
} else if (num_bytes <= 16 && IsArmv7kProcess()) {
// "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"
+ // 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);
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index e301b21d542a..85f864ec7561 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -1760,8 +1760,8 @@ bool ABIMacOSX_arm64::GetArgumentValues(Thread &thread,
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
@@ -2022,10 +2022,9 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
}
// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says
-// registers x19 through x28 and sp are callee preserved.
-// v8-v15 are non-volatile (and specifically only the lower 8 bytes of these
-// regs),
-// the rest of the fp/SIMD registers are volatile.
+// registers x19 through x28 and sp are callee preserved. v8-v15 are non-
+// volatile (and specifically only the lower 8 bytes of these regs), the rest
+// of the fp/SIMD registers are volatile.
// We treat x29 as callee preserved also, else the unwinder won't try to
// retrieve fp saves.
@@ -2209,14 +2208,14 @@ static bool LoadValueFromConsecutiveGPRRegisters(
} else {
const RegisterInfo *reg_info = nullptr;
if (is_return_value) {
- // We are assuming we are decoding this immediately after returning
- // from a function call and that the address of the structure is in x8
+ // We are assuming we are decoding this immediately after returning from
+ // a function call and that the address of the structure is in x8
reg_info = reg_ctx->GetRegisterInfoByName("x8", 0);
} else {
// We are assuming we are stopped at the first instruction in a function
- // and that the ABI is being respected so all parameters appear where they
- // should be (functions with no external linkage can legally violate the
- // ABI).
+ // and that the ABI is being respected so all parameters appear where
+ // they should be (functions with no external linkage can legally violate
+ // the ABI).
if (NGRN >= 8)
return false;
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 716a73b854b3..9e5e39ec28ca 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -736,10 +736,10 @@ bool ABIMacOSX_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
- // When writing a register value down to memory, the register info used
- // to write memory just needs to have the correct size of a 32 bit register,
- // the actual register it pertains to is not important, just the size needs
- // to be correct. Here we use "eax"...
+ // When writing a register value down to memory, the register info used to
+ // write memory just needs to have the correct size of a 32 bit register, the
+ // actual register it pertains to is not important, just the size needs to be
+ // correct. Here we use "eax"...
const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
if (!reg_info_32)
return false; // TODO this should actually never happen
@@ -828,8 +828,8 @@ bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type(value->GetCompilerType());
if (compiler_type) {
bool is_signed;
@@ -1075,12 +1075,13 @@ bool ABIMacOSX_i386::RegisterIsVolatile(const RegisterInfo *reg_info) {
}
// v.
-// http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
+// http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130
+// -IA-
+// 32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
//
// This document ("OS X ABI Function Call Guide", chapter "IA-32 Function
-// Calling Conventions")
-// says that the following registers on i386 are preserved aka non-volatile aka
-// callee-saved:
+// Calling Conventions") says that the following registers on i386 are
+// preserved aka non-volatile aka callee-saved:
//
// ebx, ebp, esi, edi, esp
diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
index 882d5cd23e58..af7ac469e6db 100644
--- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
+++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -1470,8 +1470,8 @@ bool ABISysV_arm::GetArgumentValues(Thread &thread, ValueList &values) const {
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
index dbe333c4649e..2c221689954c 100644
--- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
+++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
@@ -1763,8 +1763,8 @@ bool ABISysV_arm64::GetArgumentValues(Thread &thread, ValueList &values) const {
addr_t sp = 0;
for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx) {
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
Value *value = values.GetValueAtIndex(value_idx);
if (!value)
@@ -1994,10 +1994,9 @@ bool ABISysV_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
}
// AAPCS64 (Procedure Call Standard for the ARM 64-bit Architecture) says
-// registers x19 through x28 and sp are callee preserved.
-// v8-v15 are non-volatile (and specifically only the lower 8 bytes of these
-// regs),
-// the rest of the fp/SIMD registers are volatile.
+// registers x19 through x28 and sp are callee preserved. v8-v15 are non-
+// volatile (and specifically only the lower 8 bytes of these regs), the rest
+// of the fp/SIMD registers are volatile.
// We treat x29 as callee preserved also, else the unwinder won't try to
// retrieve fp saves.
@@ -2020,10 +2019,10 @@ bool ABISysV_arm64::RegisterIsVolatile(const RegisterInfo *reg_info) {
if (name[0] == 'x' || name[0] == 'r') {
// Volatile registers: x0-x18
- // Although documentation says only x19-28 + sp are callee saved
- // We ll also have to treat x30 as non-volatile.
- // Each dwarf frame has its own value of lr.
- // Return false for the non-volatile gpr regs, true for everything else
+ // Although documentation says only x19-28 + sp are callee saved We ll
+ // also have to treat x30 as non-volatile. Each dwarf frame has its own
+ // value of lr. Return false for the non-volatile gpr regs, true for
+ // everything else
switch (name[1]) {
case '1':
switch (name[2]) {
@@ -2180,14 +2179,14 @@ static bool LoadValueFromConsecutiveGPRRegisters(
} else {
const RegisterInfo *reg_info = nullptr;
if (is_return_value) {
- // We are assuming we are decoding this immediately after returning
- // from a function call and that the address of the structure is in x8
+ // We are assuming we are decoding this immediately after returning from
+ // a function call and that the address of the structure is in x8
reg_info = reg_ctx->GetRegisterInfoByName("x8", 0);
} else {
// We are assuming we are stopped at the first instruction in a function
- // and that the ABI is being respected so all parameters appear where they
- // should be (functions with no external linkage can legally violate the
- // ABI).
+ // and that the ABI is being respected so all parameters appear where
+ // they should be (functions with no external linkage can legally violate
+ // the ABI).
if (NGRN >= 8)
return false;
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
index 74274f08b24f..a30416cf5a8e 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -1214,8 +1214,8 @@ ValueObjectSP ABISysV_hexagon::GetReturnValueObjectImpl(
return return_valobj_sp;
}
-// called when we are on the first instruction of a new function
-// for hexagon the return address is in RA (R31)
+// called when we are on the first instruction of a new function for hexagon
+// the return address is in RA (R31)
bool ABISysV_hexagon::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindGeneric);
diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
index d799c587dd07..e7ddfccea338 100644
--- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
+++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
@@ -3,8 +3,7 @@
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
-// License.
-// See LICENSE.TXT for details.
+// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
#include "ABISysV_i386.h"
@@ -56,8 +55,8 @@ using namespace lldb_private;
// DWARF Register Number Mapping
// See Table 2.14 of the reference document (specified on top of this file)
-// Comment: Table 2.14 is followed till 'mm' entries.
-// After that, all entries are ignored here.
+// Comment: Table 2.14 is followed till 'mm' entries. After that, all entries
+// are ignored here.
enum dwarf_regnums {
dwarf_eax = 0,
@@ -228,12 +227,10 @@ bool ABISysV_i386::PrepareTrivialCall(Thread &thread, addr_t sp,
uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
- // While using register info to write a register value to memory, the register
- // info
- // just needs to have the correct size of a 32 bit register, the actual
- // register it
- // pertains to is not important, just the size needs to be correct.
- // "eax" is used here for this purpose.
+ // While using register info to write a register value to memory, the
+ // register info just needs to have the correct size of a 32 bit register,
+ // the actual register it pertains to is not important, just the size needs
+ // to be correct. "eax" is used here for this purpose.
const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
if (!reg_info_32)
return false; // TODO this should actually never happen
@@ -364,8 +361,8 @@ Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
}
// 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)
+ // 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'
{
@@ -390,8 +387,8 @@ Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
default:
break;
case 16:
- // For clang::BuiltinType::UInt128 & Int128
- // ToDo: Need to decide how to handle it
+ // 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);
@@ -470,8 +467,8 @@ Status ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
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.
+ // 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 {
@@ -508,8 +505,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
// Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
- // The terminology 'Fundamental Data Types' used here is adopted from
- // Table 2.1 of the reference document (specified on top of this file)
+ // 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'
{
@@ -543,8 +540,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
break;
case 16:
- // For clang::BuiltinType::UInt128 & Int128
- // ToDo: Need to decide how to handle it
+ // For clang::BuiltinType::UInt128 & Int128 ToDo: Need to decide how to
+ // handle it
break;
case 8:
@@ -612,8 +609,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
success = true;
} else if (byte_size == 8) // double is 8 bytes
{
- // On Android Platform: long double is also 8 bytes
- // It will be handled here only.
+ // On Android Platform: long double is also 8 bytes It will be
+ // handled here only.
double value_double = (double)value_long_double;
value.GetScalar() = value_double;
success = true;
@@ -639,8 +636,8 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
}
} else // Neither 'Integral' nor 'Floating Point'
{
- // If flow reaches here then check type_flags
- // This type_flags is unhandled
+ // If flow reaches here then check type_flags This type_flags is
+ // unhandled
}
} else if (type_flags & eTypeIsComplex) // 'Complex Floating Point'
{
@@ -797,9 +794,9 @@ bool ABISysV_i386::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
return true;
}
-// According to "Register Usage" in reference document (specified on top
-// of this source file) ebx, ebp, esi, edi and esp registers are preserved
-// i.e. non-volatile i.e. callee-saved on i386
+// According to "Register Usage" in reference document (specified on top of
+// this source file) ebx, ebp, esi, edi and esp registers are preserved i.e.
+// non-volatile i.e. callee-saved on i386
bool ABISysV_i386::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (!reg_info)
return false;
diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
index 95e2a7b0afeb..ce02f8677a63 100644
--- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
+++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
@@ -698,8 +698,8 @@ bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
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)
+ // 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;
@@ -867,8 +867,8 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
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.
+ // 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
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
index 749e170fa17d..b958abf25637 100644
--- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
@@ -661,8 +661,8 @@ bool ABISysV_mips64::PrepareTrivialCall(Thread &thread, addr_t sp,
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)
+ // 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;
@@ -1035,10 +1035,9 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
}
}
- // 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.
+ // 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;
@@ -1049,8 +1048,8 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
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 we don't know the size of the field (e.g. invalid type), just
+ // bail out
if (field_byte_width == 0)
break;
@@ -1078,16 +1077,15 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
}
}
// 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.
+ // 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
- // nullptr return value object.
+ // 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 nullptr return value
+ // object.
return return_valobj_sp;
}
}
@@ -1123,15 +1121,16 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
sucess = 1;
}
if (sucess) {
- // The result is in our data buffer. Create a variable object out of it
+ // 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.
+ // 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);
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
index 2fee176739f3..e93dcdbe1a59 100644
--- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -402,8 +402,8 @@ bool ABISysV_ppc::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -501,8 +501,8 @@ Status ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -735,10 +735,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
copy_from_offset = integer_bytes - 8;
integer_bytes += field_byte_width;
} else {
- // The last field didn't fit. I can't see how that would happen w/o
- // the overall size being
- // greater than 16 bytes. For now, return a nullptr return value
- // object.
+ // The last field didn't fit. I can't see how that would happen
+ // w/o the overall size being greater than 16 bytes. For now,
+ // return a nullptr return value object.
return return_valobj_sp;
}
} else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
@@ -751,10 +750,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
fp_bytes += field_byte_width;
} else if (field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
- // with another float, we'll
- // be stuffed into an xmm register with it. If we are in an
- // "eightbyte" with one or more ints,
- // then we will be stuffed into the appropriate GPR with them.
+ // with another float, we'll be stuffed into an xmm register with
+ // it. If we are in an "eightbyte" with one or more ints, then we
+ // will be stuffed into the appropriate GPR with them.
bool in_gpr;
if (field_byte_offset % 8 == 0) {
// We are at the beginning of one of the eightbytes, so check the
@@ -776,9 +774,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
}
}
} else if (field_byte_offset % 4 == 0) {
- // We are inside of an eightbyte, so see if the field before us is
- // floating point:
- // This could happen if somebody put padding in the structure.
+ // We are inside of an eightbyte, so see if the field before us
+ // is floating point: This could happen if somebody put padding
+ // in the structure.
if (idx == 0)
in_gpr = false;
else {
@@ -819,9 +817,9 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
}
}
- // These two tests are just sanity checks. If I somehow get the
- // type calculation wrong above it is better to just return nothing
- // than to assert or crash.
+ // These two tests are just sanity checks. If I somehow get the type
+ // calculation wrong above it is better to just return nothing than to
+ // assert or crash.
if (!copy_from_extractor)
return return_valobj_sp;
if (copy_from_offset + field_byte_width >
@@ -845,9 +843,8 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
// FIXME: This is just taking a guess, r3 may very well no longer hold the
// return storage location.
// If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
+ // check to see if it uses a memory return, and if we are at the first
+ // instruction and if so stash away the return location. Then we would
// only return the memory return value if we know it is valid.
if (is_memory) {
@@ -918,9 +915,9 @@ bool ABISysV_ppc::RegisterIsVolatile(const RegisterInfo *reg_info) {
// See "Register Usage" in the
// "System V Application Binary Interface"
-// "64-bit PowerPC ELF Application Binary Interface Supplement"
-// current version is 1.9 released 2004 at
-// http://refspecs.linuxfoundation.org/ELF/ppc/PPC-elf64abi-1.9.pdf
+// "64-bit PowerPC ELF Application Binary Interface Supplement" current version
+// is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc/PPC-
+// elf64abi-1.9.pdf
bool ABISysV_ppc::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (reg_info) {
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
index 0348853c7fa0..d0140a0c894a 100644
--- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -16,6 +16,8 @@
#include "llvm/ADT/Triple.h"
// Project includes
+#include "Utility/PPC64LE_DWARF_Registers.h"
+#include "Utility/PPC64_DWARF_Registers.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegisterValue.h"
@@ -23,6 +25,7 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -34,201 +37,48 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
-using namespace lldb;
-using namespace lldb_private;
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/Decl.h"
-enum dwarf_regnums {
- 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,
-};
+#define DECLARE_REGISTER_INFOS_PPC64_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64.h"
+#undef DECLARE_REGISTER_INFOS_PPC64_STRUCT
-// Note that the size and offset will be updated by platform-specific classes.
-#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
- { \
- #reg, alt, 8, 0, eEncodingUint, eFormatHex, {kind1, kind2, kind3, kind4 }, \
- nullptr, nullptr, nullptr, 0 \
- }
+#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
+#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
-static const RegisterInfo g_register_infos[] = {
- // General purpose registers. eh_frame, DWARF,
- // Generic, Process Plugin
- DEFINE_GPR(r0, nullptr, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r2, nullptr, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r3, "arg1", dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r4, "arg2", dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r5, "arg3", dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r6, "arg4", dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r7, "arg5", dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r8, "arg6", dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r9, "arg7", dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r10, "arg8", dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r11, nullptr, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r12, nullptr, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r13, nullptr, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r14, nullptr, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r15, nullptr, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r16, nullptr, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r17, nullptr, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r18, nullptr, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r19, nullptr, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r20, nullptr, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r21, nullptr, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r22, nullptr, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r23, nullptr, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r24, nullptr, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r25, nullptr, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r26, nullptr, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r27, nullptr, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r28, nullptr, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r29, nullptr, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r30, nullptr, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(r31, nullptr, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC,
- LLDB_INVALID_REGNUM),
- {nullptr,
- nullptr,
- 8,
- 0,
- eEncodingUint,
- eFormatHex,
- {dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM},
- nullptr,
- nullptr,
- nullptr,
- 0}};
-
-static const uint32_t k_num_register_infos =
- llvm::array_lengthof(g_register_infos);
+using namespace lldb;
+using namespace lldb_private;
const lldb_private::RegisterInfo *
ABISysV_ppc64::GetRegisterInfoArray(uint32_t &count) {
- count = k_num_register_infos;
- return g_register_infos;
+ if (GetByteOrder() == lldb::eByteOrderLittle) {
+ count = llvm::array_lengthof(g_register_infos_ppc64le);
+ return g_register_infos_ppc64le;
+ } else {
+ count = llvm::array_lengthof(g_register_infos_ppc64);
+ return g_register_infos_ppc64;
+ }
}
size_t ABISysV_ppc64::GetRedZoneSize() const { return 224; }
+lldb::ByteOrder ABISysV_ppc64::GetByteOrder() const {
+ return GetProcessSP()->GetByteOrder();
+}
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
ABISP
-ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
- if (arch.GetTriple().getArch() == llvm::Triple::ppc64) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_ppc64(process_sp));
- return g_abi_sp;
+ABISysV_ppc64::CreateInstance(lldb::ProcessSP process_sp,
+ const ArchSpec &arch) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64 ||
+ arch.GetTriple().getArch() == llvm::Triple::ppc64le) {
+ return ABISP(new ABISysV_ppc64(process_sp));
}
return ABISP();
}
@@ -280,28 +130,68 @@ bool ABISysV_ppc64::PrepareTrivialCall(Thread &thread, addr_t sp,
sp &= ~(0xfull); // 16-byte alignment
- sp -= 8;
+ sp -= 544; // allocate frame to save TOC, RA and SP.
Status error;
+ uint64_t reg_value;
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);
ProcessSP process_sp(thread.GetProcess());
+ const RegisterInfo *lr_reg_info =
+ reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoAtIndex(2);
+ const RegisterInfo *r12_reg_info = reg_ctx->GetRegisterInfoAtIndex(12);
- RegisterValue reg_value;
-
+ // Save return address onto the stack.
if (log)
log->Printf("Pushing the return address onto the stack: 0x%" PRIx64
- ": 0x%" PRIx64,
+ "(+16): 0x%" PRIx64,
(uint64_t)sp, (uint64_t)return_addr);
+ if (!process_sp->WritePointerToMemory(sp + 16, return_addr, error))
+ return false;
- // Save return address onto the stack
- if (!process_sp->WritePointerToMemory(sp, return_addr, error))
+ // Write the return address to link register.
+ if (log)
+ log->Printf("Writing LR: 0x%" PRIx64, (uint64_t)return_addr);
+ if (!reg_ctx->WriteRegisterFromUnsigned(lr_reg_info, return_addr))
return false;
- // %r1 is set to the actual stack value.
+ // Write target address to %r12 register.
+ if (log)
+ log->Printf("Writing R12: 0x%" PRIx64, (uint64_t)func_addr);
+ if (!reg_ctx->WriteRegisterFromUnsigned(r12_reg_info, func_addr))
+ return false;
+
+ // Read TOC pointer value.
+ reg_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
+
+ // Write TOC pointer onto the stack.
+ uint64_t stack_offset;
+ if (GetByteOrder() == lldb::eByteOrderLittle)
+ stack_offset = 24;
+ else
+ stack_offset = 40;
+
+ if (log)
+ log->Printf("Writing R2 (TOC) at SP(0x%" PRIx64 ")+%d: 0x%" PRIx64,
+ (uint64_t)(sp + stack_offset), (int)stack_offset,
+ (uint64_t)reg_value);
+ if (!process_sp->WritePointerToMemory(sp + stack_offset, reg_value, error))
+ return false;
+
+ // Read the current SP value.
+ reg_value = reg_ctx->ReadRegisterAsUnsigned(sp_reg_info, 0);
+
+ // Save current SP onto the stack.
+ if (log)
+ log->Printf("Writing SP at SP(0x%" PRIx64 ")+0: 0x%" PRIx64, (uint64_t)sp,
+ (uint64_t)reg_value);
+ if (!process_sp->WritePointerToMemory(sp, reg_value, error))
+ return false;
+ // %r1 is set to the actual stack value.
if (log)
log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
@@ -365,34 +255,23 @@ bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!sp)
return false;
- addr_t current_stack_argument = sp + 48; // jump over return address
+ uint64_t stack_offset;
+ if (GetByteOrder() == lldb::eByteOrderLittle)
+ stack_offset = 32;
+ else
+ stack_offset = 48;
+ // jump over return address.
+ addr_t current_stack_argument = sp + stack_offset;
uint32_t argument_register_ids[8];
- argument_register_ids[0] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[1] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[2] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[3] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[4] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[5] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[6] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)
- ->kinds[eRegisterKindLLDB];
- argument_register_ids[7] =
- reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)
- ->kinds[eRegisterKindLLDB];
+ for (size_t i = 0; i < 8; ++i) {
+ argument_register_ids[i] =
+ reg_ctx
+ ->GetRegisterInfo(eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_ARG1 + i)
+ ->kinds[eRegisterKindLLDB];
+ }
unsigned int current_argument_register = 0;
@@ -402,8 +281,8 @@ bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -501,8 +380,8 @@ Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -510,367 +389,584 @@ Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
return error;
}
-ValueObjectSP ABISysV_ppc64::GetReturnValueObjectSimple(
- Thread &thread, CompilerType &return_compiler_type) const {
- ValueObjectSP return_valobj_sp;
- Value value;
+//
+// ReturnValueExtractor
+//
- if (!return_compiler_type)
- return return_valobj_sp;
+namespace {
+
+#define LOG_PREFIX "ReturnValueExtractor: "
+
+class ReturnValueExtractor {
+ // This class represents a register, from which data may be extracted.
+ //
+ // It may be constructed by directly specifying its index (where 0 is the
+ // first register used to return values) or by specifying the offset of a
+ // given struct field, in which case the appropriated register index will be
+ // calculated.
+ class Register {
+ public:
+ enum Type {
+ GPR, // General Purpose Register
+ FPR // Floating Point Register
+ };
+
+ // main constructor
+ //
+ // offs - field offset in struct
+ Register(Type ty, uint32_t index, uint32_t offs, RegisterContext *reg_ctx,
+ ByteOrder byte_order)
+ : m_index(index), m_offs(offs % sizeof(uint64_t)),
+ m_avail(sizeof(uint64_t) - m_offs), m_type(ty), m_reg_ctx(reg_ctx),
+ m_byte_order(byte_order) {}
+
+ // explicit index, no offset
+ Register(Type ty, uint32_t index, RegisterContext *reg_ctx,
+ ByteOrder byte_order)
+ : Register(ty, index, 0, reg_ctx, byte_order) {}
+
+ // GPR, calculate index from offs
+ Register(uint32_t offs, RegisterContext *reg_ctx, ByteOrder byte_order)
+ : Register(GPR, offs / sizeof(uint64_t), offs, reg_ctx, byte_order) {}
+
+ uint32_t Index() const { return m_index; }
+
+ // register offset where data is located
+ uint32_t Offs() const { return m_offs; }
+
+ // available bytes in this register
+ uint32_t Avail() const { return m_avail; }
+
+ bool IsValid() const {
+ if (m_index > 7) {
+ LLDB_LOG(m_log, LOG_PREFIX
+ "No more than 8 registers should be used to return values");
+ return false;
+ }
+ return true;
+ }
- // value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetCompilerType(return_compiler_type);
+ std::string GetName() const {
+ if (m_type == GPR)
+ return ("r" + llvm::Twine(m_index + 3)).str();
+ else
+ return ("f" + llvm::Twine(m_index + 1)).str();
+ }
- RegisterContext *reg_ctx = thread.GetRegisterContext().get();
- if (!reg_ctx)
- return return_valobj_sp;
-
- const uint32_t type_flags = return_compiler_type.GetTypeInfo();
- if (type_flags & eTypeIsScalar) {
- value.SetValueType(Value::eValueTypeScalar);
-
- bool success = false;
- if (type_flags & eTypeIsInteger) {
- // Extract the register context so we can read arguments from registers
-
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
- reg_ctx->GetRegisterInfoByName("r3", 0), 0);
- const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
- default:
- break;
-
- case sizeof(uint64_t):
- if (is_signed)
- value.GetScalar() = (int64_t)(raw_value);
- else
- value.GetScalar() = (uint64_t)(raw_value);
- success = true;
- break;
-
- case sizeof(uint32_t):
- if (is_signed)
- value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
- else
- value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
- success = true;
- break;
-
- case sizeof(uint16_t):
- if (is_signed)
- value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
- else
- value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
- success = true;
- break;
-
- case sizeof(uint8_t):
- if (is_signed)
- value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
- else
- value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
- success = true;
- break;
+ // get raw register data
+ bool GetRawData(uint64_t &raw_data) {
+ const RegisterInfo *reg_info =
+ m_reg_ctx->GetRegisterInfoByName(GetName());
+ if (!reg_info) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get RegisterInfo");
+ return false;
}
- } else if (type_flags & eTypeIsFloat) {
- if (type_flags & eTypeIsComplex) {
- // Don't handle complex yet.
- } else {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size <= sizeof(long double)) {
- const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
- RegisterValue f1_value;
- if (reg_ctx->ReadRegister(f1_info, f1_value)) {
- DataExtractor data;
- if (f1_value.GetData(data)) {
- lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
- value.GetScalar() = (float)data.GetFloat(&offset);
- success = true;
- } else if (byte_size == sizeof(double)) {
- value.GetScalar() = (double)data.GetDouble(&offset);
- success = true;
- }
- }
- }
- }
+
+ RegisterValue reg_val;
+ if (!m_reg_ctx->ReadRegister(reg_info, reg_val)) {
+ LLDB_LOG(m_log, LOG_PREFIX "ReadRegister() failed");
+ return false;
}
+
+ Status error;
+ uint32_t rc = reg_val.GetAsMemoryData(
+ reg_info, &raw_data, sizeof(raw_data), m_byte_order, error);
+ if (rc != sizeof(raw_data)) {
+ LLDB_LOG(m_log, LOG_PREFIX "GetAsMemoryData() failed");
+ return false;
+ }
+
+ return true;
}
- if (success)
- return_valobj_sp = ValueObjectConstResult::Create(
- thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
- } else if (type_flags & eTypeIsPointer) {
- unsigned r3_id =
- reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
- value.GetScalar() =
- (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
- value.SetValueType(Value::eValueTypeScalar);
- return_valobj_sp = ValueObjectConstResult::Create(
- thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
- } else if (type_flags & eTypeIsVector) {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size > 0) {
- const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0);
- if (altivec_reg) {
- if (byte_size <= altivec_reg->byte_size) {
- ProcessSP process_sp(thread.GetProcess());
- if (process_sp) {
- std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
- const ByteOrder byte_order = process_sp->GetByteOrder();
- RegisterValue reg_value;
- if (reg_ctx->ReadRegister(altivec_reg, reg_value)) {
- Status error;
- if (reg_value.GetAsMemoryData(
- altivec_reg, heap_data_ap->GetBytes(),
- heap_data_ap->GetByteSize(), 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);
- }
- }
- }
+ private:
+ uint32_t m_index;
+ uint32_t m_offs;
+ uint32_t m_avail;
+ Type m_type;
+ RegisterContext *m_reg_ctx;
+ ByteOrder m_byte_order;
+ Log *m_log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ };
+
+ Register GetGPR(uint32_t index) const {
+ return Register(Register::GPR, index, m_reg_ctx, m_byte_order);
+ }
+
+ Register GetFPR(uint32_t index) const {
+ return Register(Register::FPR, index, m_reg_ctx, m_byte_order);
+ }
+
+ Register GetGPRByOffs(uint32_t offs) const {
+ return Register(offs, m_reg_ctx, m_byte_order);
+ }
+
+public:
+ // factory
+ static llvm::Expected<ReturnValueExtractor> Create(Thread &thread,
+ CompilerType &type) {
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return llvm::make_error<llvm::StringError>(
+ LOG_PREFIX "Failed to get RegisterContext",
+ llvm::inconvertibleErrorCode());
+
+ ProcessSP process_sp = thread.GetProcess();
+ if (!process_sp)
+ return llvm::make_error<llvm::StringError>(
+ LOG_PREFIX "GetProcess() failed", llvm::inconvertibleErrorCode());
+
+ return ReturnValueExtractor(thread, type, reg_ctx, process_sp);
+ }
+
+ // main method: get value of the type specified at construction time
+ ValueObjectSP GetValue() {
+ const uint32_t type_flags = m_type.GetTypeInfo();
+
+ // call the appropriate type handler
+ ValueSP value_sp;
+ ValueObjectSP valobj_sp;
+ if (type_flags & eTypeIsScalar) {
+ if (type_flags & eTypeIsInteger) {
+ value_sp = GetIntegerValue(0);
+ } else if (type_flags & eTypeIsFloat) {
+ if (type_flags & eTypeIsComplex) {
+ LLDB_LOG(m_log, LOG_PREFIX "Complex numbers are not supported yet");
+ return ValueObjectSP();
+ } else {
+ value_sp = GetFloatValue(m_type, 0);
}
}
+ } else if (type_flags & eTypeIsPointer) {
+ value_sp = GetPointerValue(0);
}
+
+ if (value_sp) {
+ valobj_sp = ValueObjectConstResult::Create(
+ m_thread.GetStackFrameAtIndex(0).get(), *value_sp, ConstString(""));
+ } else if (type_flags & eTypeIsVector) {
+ valobj_sp = GetVectorValueObject();
+ } else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass) {
+ valobj_sp = GetStructValueObject();
+ }
+
+ return valobj_sp;
}
- return return_valobj_sp;
-}
+private:
+ // data
+ Thread &m_thread;
+ CompilerType &m_type;
+ uint64_t m_byte_size;
+ std::unique_ptr<DataBufferHeap> m_data_ap;
+ int32_t m_src_offs = 0;
+ int32_t m_dst_offs = 0;
+ bool m_packed = false;
+ Log *m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ RegisterContext *m_reg_ctx;
+ ProcessSP m_process_sp;
+ ByteOrder m_byte_order;
+ uint32_t m_addr_size;
+
+ // methods
+
+ // constructor
+ ReturnValueExtractor(Thread &thread, CompilerType &type,
+ RegisterContext *reg_ctx, ProcessSP process_sp)
+ : m_thread(thread), m_type(type),
+ m_byte_size(m_type.GetByteSize(nullptr)),
+ m_data_ap(new DataBufferHeap(m_byte_size, 0)), m_reg_ctx(reg_ctx),
+ m_process_sp(process_sp), m_byte_order(process_sp->GetByteOrder()),
+ m_addr_size(
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize()) {}
+
+ // build a new scalar value
+ ValueSP NewScalarValue(CompilerType &type) {
+ ValueSP value_sp(new Value);
+ value_sp->SetCompilerType(type);
+ value_sp->SetValueType(Value::eValueTypeScalar);
+ return value_sp;
+ }
-ValueObjectSP ABISysV_ppc64::GetReturnValueObjectImpl(
- Thread &thread, CompilerType &return_compiler_type) const {
- ValueObjectSP return_valobj_sp;
-
- if (!return_compiler_type)
- return return_valobj_sp;
-
- ExecutionContext exe_ctx(thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
- if (return_valobj_sp)
- return return_valobj_sp;
-
- RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
- if (!reg_ctx_sp)
- return return_valobj_sp;
-
- const size_t bit_width = return_compiler_type.GetBitSize(&thread);
- if (return_compiler_type.IsAggregateType()) {
- Target *target = exe_ctx.GetTargetPtr();
- bool is_memory = true;
- if (bit_width <= 128) {
- ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
- DataBufferSP data_sp(new DataBufferHeap(16, 0));
- DataExtractor return_ext(data_sp, target_byte_order,
- target->GetArchitecture().GetAddressByteSize());
-
- const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0);
- const RegisterInfo *rdx_info =
- reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
-
- RegisterValue r3_value, rdx_value;
- reg_ctx_sp->ReadRegister(r3_info, r3_value);
- reg_ctx_sp->ReadRegister(rdx_info, rdx_value);
-
- DataExtractor r3_data, rdx_data;
-
- r3_value.GetData(r3_data);
- rdx_value.GetData(rdx_data);
-
- 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_compiler_type.GetNumFields();
-
- // Since we are in the small struct regime, assume we are not in memory.
- is_memory = false;
-
- for (uint32_t idx = 0; idx < num_children; idx++) {
- std::string name;
- uint64_t field_bit_offset = 0;
- bool is_signed;
- bool is_complex;
- uint32_t count;
-
- CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
- idx, name, &field_bit_offset, nullptr, nullptr);
- const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
-
- // If there are any unaligned fields, this is stored in memory.
- if (field_bit_offset % field_bit_width != 0) {
- is_memory = true;
- break;
+ // get an integer value in the specified register
+ ValueSP GetIntegerValue(uint32_t reg_index) {
+ uint64_t raw_value;
+ auto reg = GetGPR(reg_index);
+ if (!reg.GetRawData(raw_value))
+ return ValueSP();
+
+ // build value from data
+ ValueSP value_sp(NewScalarValue(m_type));
+
+ uint32_t type_flags = m_type.GetTypeInfo();
+ bool is_signed = (type_flags & eTypeIsSigned) != 0;
+
+ switch (m_byte_size) {
+ case sizeof(uint64_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int64_t)(raw_value);
+ else
+ value_sp->GetScalar() = (uint64_t)(raw_value);
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value_sp->GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value_sp->GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value_sp->GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value_sp->GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ break;
+
+ default:
+ llvm_unreachable("Invalid integer size");
+ }
+
+ return value_sp;
+ }
+
+ // get a floating point value on the specified register
+ ValueSP GetFloatValue(CompilerType &type, uint32_t reg_index) {
+ uint64_t raw_data;
+ auto reg = GetFPR(reg_index);
+ if (!reg.GetRawData(raw_data))
+ return ValueSP();
+
+ // build value from data
+ ValueSP value_sp(NewScalarValue(type));
+
+ DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size);
+
+ offset_t offset = 0;
+ size_t byte_size = type.GetByteSize(nullptr);
+ switch (byte_size) {
+ case sizeof(float):
+ value_sp->GetScalar() = (float)de.GetDouble(&offset);
+ break;
+
+ case sizeof(double):
+ value_sp->GetScalar() = de.GetDouble(&offset);
+ break;
+
+ default:
+ llvm_unreachable("Invalid floating point size");
+ }
+
+ return value_sp;
+ }
+
+ // get pointer value from register
+ ValueSP GetPointerValue(uint32_t reg_index) {
+ uint64_t raw_data;
+ auto reg = GetGPR(reg_index);
+ if (!reg.GetRawData(raw_data))
+ return ValueSP();
+
+ // build value from raw data
+ ValueSP value_sp(NewScalarValue(m_type));
+ value_sp->GetScalar() = raw_data;
+ return value_sp;
+ }
+
+ // build the ValueObject from our data buffer
+ ValueObjectSP BuildValueObject() {
+ DataExtractor de(DataBufferSP(m_data_ap.release()), m_byte_order,
+ m_addr_size);
+ return ValueObjectConstResult::Create(&m_thread, m_type, ConstString(""),
+ de);
+ }
+
+ // get a vector return value
+ ValueObjectSP GetVectorValueObject() {
+ const uint32_t MAX_VRS = 2;
+
+ // get first V register used to return values
+ const RegisterInfo *vr[MAX_VRS];
+ vr[0] = m_reg_ctx->GetRegisterInfoByName("vr2");
+ if (!vr[0]) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr2 RegisterInfo");
+ return ValueObjectSP();
+ }
+
+ const uint32_t vr_size = vr[0]->byte_size;
+ size_t vrs = 1;
+ if (m_byte_size > 2 * vr_size) {
+ LLDB_LOG(
+ m_log, LOG_PREFIX
+ "Returning vectors that don't fit in 2 VR regs is not supported");
+ return ValueObjectSP();
+ }
+
+ // load vr3, if needed
+ if (m_byte_size > vr_size) {
+ vrs++;
+ vr[1] = m_reg_ctx->GetRegisterInfoByName("vr3");
+ if (!vr[1]) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get vr3 RegisterInfo");
+ return ValueObjectSP();
+ }
+ }
+
+ // Get the whole contents of vector registers and let the logic here
+ // arrange the data properly.
+
+ RegisterValue vr_val[MAX_VRS];
+ Status error;
+ std::unique_ptr<DataBufferHeap> vr_data(
+ new DataBufferHeap(vrs * vr_size, 0));
+
+ for (uint32_t i = 0; i < vrs; i++) {
+ if (!m_reg_ctx->ReadRegister(vr[i], vr_val[i])) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to read vector register contents");
+ return ValueObjectSP();
+ }
+ if (!vr_val[i].GetAsMemoryData(vr[i], vr_data->GetBytes() + i * vr_size,
+ vr_size, m_byte_order, error)) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to extract vector register bytes");
+ return ValueObjectSP();
+ }
+ }
+
+ // The compiler generated code seems to always put the vector elements at
+ // the end of the vector register, in case they don't occupy all of it.
+ // This offset variable handles this.
+ uint32_t offs = 0;
+ if (m_byte_size < vr_size)
+ offs = vr_size - m_byte_size;
+
+ // copy extracted data to our buffer
+ memcpy(m_data_ap->GetBytes(), vr_data->GetBytes() + offs, m_byte_size);
+ return BuildValueObject();
+ }
+
+ // get a struct return value
+ ValueObjectSP GetStructValueObject() {
+ // case 1: get from stack
+ if (m_byte_size > 2 * sizeof(uint64_t)) {
+ uint64_t addr;
+ auto reg = GetGPR(0);
+ if (!reg.GetRawData(addr))
+ return ValueObjectSP();
+
+ Status error;
+ size_t rc = m_process_sp->ReadMemory(addr, m_data_ap->GetBytes(),
+ m_byte_size, error);
+ if (rc != m_byte_size) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to read memory pointed by r3");
+ return ValueObjectSP();
+ }
+ return BuildValueObject();
+ }
+
+ // get number of children
+ const bool omit_empty_base_classes = true;
+ uint32_t n = m_type.GetNumChildren(omit_empty_base_classes);
+ if (!n) {
+ LLDB_LOG(m_log, LOG_PREFIX "No children found in struct");
+ return ValueObjectSP();
+ }
+
+ // case 2: homogeneous double or float aggregate
+ CompilerType elem_type;
+ if (m_type.IsHomogeneousAggregate(&elem_type)) {
+ uint32_t type_flags = elem_type.GetTypeInfo();
+ uint64_t elem_size = elem_type.GetByteSize(nullptr);
+ if (type_flags & eTypeIsComplex || !(type_flags & eTypeIsFloat)) {
+ LLDB_LOG(m_log,
+ LOG_PREFIX "Unexpected type found in homogeneous aggregate");
+ return ValueObjectSP();
+ }
+
+ for (uint32_t i = 0; i < n; i++) {
+ ValueSP val_sp = GetFloatValue(elem_type, i);
+ if (!val_sp)
+ return ValueObjectSP();
+
+ // copy to buffer
+ Status error;
+ size_t rc = val_sp->GetScalar().GetAsMemoryData(
+ m_data_ap->GetBytes() + m_dst_offs, elem_size, m_byte_order, error);
+ if (rc != elem_size) {
+ LLDB_LOG(m_log, LOG_PREFIX "Failed to get float data");
+ return ValueObjectSP();
}
+ m_dst_offs += elem_size;
+ }
+ return BuildValueObject();
+ }
- uint32_t field_byte_width = field_bit_width / 8;
- uint32_t field_byte_offset = field_bit_offset / 8;
-
- DataExtractor *copy_from_extractor = nullptr;
- uint32_t copy_from_offset = 0;
-
- if (field_compiler_type.IsIntegerOrEnumerationType(is_signed) ||
- field_compiler_type.IsPointerType()) {
- if (integer_bytes < 8) {
- if (integer_bytes + field_byte_width <= 8) {
- // This is in RAX, copy from register to our result structure:
- copy_from_extractor = &r3_data;
- copy_from_offset = integer_bytes;
- integer_bytes += field_byte_width;
- } else {
- // The next field wouldn't fit in the remaining space, so we
- // pushed it to rdx.
- copy_from_extractor = &rdx_data;
- copy_from_offset = 0;
- integer_bytes = 8 + field_byte_width;
- }
- } else if (integer_bytes + field_byte_width <= 16) {
- copy_from_extractor = &rdx_data;
- copy_from_offset = integer_bytes - 8;
- integer_bytes += field_byte_width;
- } else {
- // The last field didn't fit. I can't see how that would happen w/o
- // the overall size being
- // greater than 16 bytes. For now, return a nullptr return value
- // object.
- return return_valobj_sp;
- }
- } else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
- // Structs with long doubles are always passed in memory.
- if (field_bit_width == 128) {
- is_memory = true;
+ // case 3: get from GPRs
+
+ // first, check if this is a packed struct or not
+ ClangASTContext *ast =
+ llvm::dyn_cast<ClangASTContext>(m_type.GetTypeSystem());
+ if (ast) {
+ clang::RecordDecl *record_decl = ClangASTContext::GetAsRecordDecl(m_type);
+
+ if (record_decl) {
+ auto attrs = record_decl->attrs();
+ for (const auto &attr : attrs) {
+ if (attr->getKind() == clang::attr::Packed) {
+ m_packed = true;
break;
- } else if (field_bit_width == 64) {
- copy_from_offset = 0;
- fp_bytes += field_byte_width;
- } else if (field_bit_width == 32) {
- // This one is kind of complicated. If we are in an "eightbyte"
- // with another float, we'll
- // be stuffed into an xmm register with it. If we are in an
- // "eightbyte" with one or more ints,
- // then we will be stuffed into the appropriate GPR with them.
- bool in_gpr;
- if (field_byte_offset % 8 == 0) {
- // We are at the beginning of one of the eightbytes, so check the
- // next element (if any)
- if (idx == num_children - 1)
- in_gpr = false;
- else {
- uint64_t next_field_bit_offset = 0;
- CompilerType next_field_compiler_type =
- return_compiler_type.GetFieldAtIndex(idx + 1, name,
- &next_field_bit_offset,
- nullptr, nullptr);
- if (next_field_compiler_type.IsIntegerOrEnumerationType(
- is_signed))
- in_gpr = true;
- else {
- copy_from_offset = 0;
- in_gpr = false;
- }
- }
- } else if (field_byte_offset % 4 == 0) {
- // We are inside of an eightbyte, so see if the field before us is
- // floating point:
- // This could happen if somebody put padding in the structure.
- if (idx == 0)
- in_gpr = false;
- else {
- uint64_t prev_field_bit_offset = 0;
- CompilerType prev_field_compiler_type =
- return_compiler_type.GetFieldAtIndex(idx - 1, name,
- &prev_field_bit_offset,
- nullptr, nullptr);
- if (prev_field_compiler_type.IsIntegerOrEnumerationType(
- is_signed))
- in_gpr = true;
- else {
- copy_from_offset = 4;
- in_gpr = false;
- }
- }
- } else {
- is_memory = true;
- continue;
- }
-
- // Okay, we've figured out whether we are in GPR or XMM, now figure
- // out which one.
- if (in_gpr) {
- if (integer_bytes < 8) {
- // This is in RAX, copy from register to our result structure:
- copy_from_extractor = &r3_data;
- copy_from_offset = integer_bytes;
- integer_bytes += field_byte_width;
- } else {
- copy_from_extractor = &rdx_data;
- copy_from_offset = integer_bytes - 8;
- integer_bytes += field_byte_width;
- }
- } else {
- fp_bytes += field_byte_width;
- }
}
}
-
- // These two tests are just sanity checks. If I somehow get the
- // type calculation wrong above it is better to just return nothing
- // than to assert or crash.
- if (!copy_from_extractor)
- return return_valobj_sp;
- if (copy_from_offset + field_byte_width >
- copy_from_extractor->GetByteSize())
- return return_valobj_sp;
-
- copy_from_extractor->CopyByteOrderedData(
- copy_from_offset, field_byte_width,
- data_sp->GetBytes() + field_byte_offset, field_byte_width,
- target_byte_order);
}
+ }
- if (!is_memory) {
- // The result is in our data buffer. Let's make a variable object out
- // of it:
- return_valobj_sp = ValueObjectConstResult::Create(
- &thread, return_compiler_type, ConstString(""), return_ext);
- }
+ LLDB_LOG(m_log, LOG_PREFIX "{0} struct",
+ m_packed ? "packed" : "not packed");
+
+ for (uint32_t i = 0; i < n; i++) {
+ std::string name;
+ uint32_t size;
+ GetChildType(i, name, size);
+ // NOTE: the offset returned by GetChildCompilerTypeAtIndex()
+ // can't be used because it never considers alignment bytes
+ // between struct fields.
+ LLDB_LOG(m_log, LOG_PREFIX "field={0}, size={1}", name, size);
+ if (!ExtractField(size))
+ return ValueObjectSP();
}
- // FIXME: This is just taking a guess, r3 may very well no longer hold the
- // return storage location.
- // If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
- // only return the memory return value if we know it is valid.
-
- if (is_memory) {
- unsigned r3_id =
- reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
- lldb::addr_t storage_addr =
- (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id,
- 0);
- return_valobj_sp = ValueObjectMemory::Create(
- &thread, "", Address(storage_addr, nullptr), return_compiler_type);
+ return BuildValueObject();
+ }
+
+ // extract 'size' bytes at 'offs' from GPRs
+ bool ExtractFromRegs(int32_t offs, uint32_t size, void *buf) {
+ while (size) {
+ auto reg = GetGPRByOffs(offs);
+ if (!reg.IsValid())
+ return false;
+
+ uint32_t n = std::min(reg.Avail(), size);
+ uint64_t raw_data;
+
+ if (!reg.GetRawData(raw_data))
+ return false;
+
+ memcpy(buf, (char *)&raw_data + reg.Offs(), n);
+ offs += n;
+ size -= n;
+ buf = (char *)buf + n;
}
+ return true;
}
- return return_valobj_sp;
+ // extract one field from GPRs and put it in our buffer
+ bool ExtractField(uint32_t size) {
+ auto reg = GetGPRByOffs(m_src_offs);
+ if (!reg.IsValid())
+ return false;
+
+ // handle padding
+ if (!m_packed) {
+ uint32_t n = m_src_offs % size;
+
+ // not 'size' bytes aligned
+ if (n) {
+ LLDB_LOG(m_log,
+ LOG_PREFIX "Extracting {0} alignment bytes at offset {1}", n,
+ m_src_offs);
+ // get alignment bytes
+ if (!ExtractFromRegs(m_src_offs, n, m_data_ap->GetBytes() + m_dst_offs))
+ return false;
+ m_src_offs += n;
+ m_dst_offs += n;
+ }
+ }
+
+ // get field
+ LLDB_LOG(m_log, LOG_PREFIX "Extracting {0} field bytes at offset {1}", size,
+ m_src_offs);
+ if (!ExtractFromRegs(m_src_offs, size, m_data_ap->GetBytes() + m_dst_offs))
+ return false;
+ m_src_offs += size;
+ m_dst_offs += size;
+ return true;
+ }
+
+ // get child
+ CompilerType GetChildType(uint32_t i, std::string &name, uint32_t &size) {
+ // GetChild constant inputs
+ const bool transparent_pointers = false;
+ const bool omit_empty_base_classes = true;
+ const bool ignore_array_bounds = false;
+ // GetChild output params
+ int32_t child_offs;
+ uint32_t child_bitfield_bit_size;
+ uint32_t child_bitfield_bit_offset;
+ bool child_is_base_class;
+ bool child_is_deref_of_parent;
+ ValueObject *valobj = nullptr;
+ uint64_t language_flags;
+ ExecutionContext exe_ctx;
+ m_thread.CalculateExecutionContext(exe_ctx);
+
+ return m_type.GetChildCompilerTypeAtIndex(
+ &exe_ctx, i, transparent_pointers, omit_empty_base_classes,
+ ignore_array_bounds, name, size, child_offs, child_bitfield_bit_size,
+ child_bitfield_bit_offset, child_is_base_class,
+ child_is_deref_of_parent, valobj, language_flags);
+ }
+};
+
+#undef LOG_PREFIX
+
+} // anonymous namespace
+
+ValueObjectSP
+ABISysV_ppc64::GetReturnValueObjectSimple(Thread &thread,
+ CompilerType &type) const {
+ if (!type)
+ return ValueObjectSP();
+
+ auto exp_extractor = ReturnValueExtractor::Create(thread, type);
+ if (!exp_extractor) {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
+ LLDB_LOG_ERROR(log, exp_extractor.takeError(),
+ "Extracting return value failed: {0}");
+ return ValueObjectSP();
+ }
+
+ return exp_extractor.get().GetValue();
+}
+
+ValueObjectSP ABISysV_ppc64::GetReturnValueObjectImpl(
+ Thread &thread, CompilerType &return_compiler_type) const {
+ return GetReturnValueObjectSimple(thread, return_compiler_type);
}
bool ABISysV_ppc64::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
- uint32_t lr_reg_num = dwarf_lr;
- uint32_t sp_reg_num = dwarf_r1;
- uint32_t pc_reg_num = dwarf_pc;
+ uint32_t lr_reg_num;
+ uint32_t sp_reg_num;
+ uint32_t pc_reg_num;
+
+ if (GetByteOrder() == lldb::eByteOrderLittle) {
+ lr_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le;
+ sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le;
+ pc_reg_num = ppc64le_dwarf::dwarf_pc_ppc64le;
+ } else {
+ lr_reg_num = ppc64_dwarf::dwarf_lr_ppc64;
+ sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64;
+ pc_reg_num = ppc64_dwarf::dwarf_pc_ppc64;
+ }
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -893,23 +989,33 @@ bool ABISysV_ppc64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
- uint32_t sp_reg_num = dwarf_r1;
- uint32_t pc_reg_num = dwarf_lr;
+ uint32_t sp_reg_num;
+ uint32_t pc_reg_num;
+ uint32_t cr_reg_num;
- UnwindPlan::RowSP row(new UnwindPlan::Row);
+ if (GetByteOrder() == lldb::eByteOrderLittle) {
+ sp_reg_num = ppc64le_dwarf::dwarf_r1_ppc64le;
+ pc_reg_num = ppc64le_dwarf::dwarf_lr_ppc64le;
+ cr_reg_num = ppc64le_dwarf::dwarf_cr_ppc64le;
+ } else {
+ sp_reg_num = ppc64_dwarf::dwarf_r1_ppc64;
+ pc_reg_num = ppc64_dwarf::dwarf_lr_ppc64;
+ cr_reg_num = ppc64_dwarf::dwarf_cr_ppc64;
+ }
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
row->GetCFAValue().SetIsRegisterDereferenced(sp_reg_num);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
- row->SetRegisterLocationToAtCFAPlusOffset(dwarf_cr, ptr_size, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(cr_reg_num, 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(dwarf_lr);
+ unwind_plan.SetReturnAddressRegister(pc_reg_num);
return true;
}
@@ -919,10 +1025,9 @@ bool ABISysV_ppc64::RegisterIsVolatile(const RegisterInfo *reg_info) {
// See "Register Usage" in the
// "System V Application Binary Interface"
-// "64-bit PowerPC ELF Application Binary Interface Supplement"
-// current version is 1.9 released 2004 at
-// http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf
-
+// "64-bit PowerPC ELF Application Binary Interface Supplement" current version
+// is 2 released 2015 at
+// https://members.openpowerfoundation.org/document/dl/576
bool ABISysV_ppc64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (reg_info) {
// Preserved registers are :
@@ -954,7 +1059,7 @@ bool ABISysV_ppc64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
return true;
if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
- return true;
+ return false;
if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
return true;
}
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
index 21608a5c1cdd..52765a773c0b 100644
--- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
@@ -108,6 +108,8 @@ private:
ABISysV_ppc64(lldb::ProcessSP process_sp) : lldb_private::ABI(process_sp) {
// Call CreateInstance instead.
}
+
+ lldb::ByteOrder GetByteOrder() const;
};
#endif // liblldb_ABISysV_ppc64_h_
diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
index 967e407188fa..31e2825c0fa2 100644
--- a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
+++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
@@ -380,8 +380,8 @@ bool ABISysV_s390x::GetArgumentValues(Thread &thread, ValueList &values) const {
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -483,8 +483,8 @@ Status ABISysV_s390x::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -618,9 +618,8 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectImpl(
// FIXME: This is just taking a guess, r2 may very well no longer hold the
// return storage location.
// If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
+ // check to see if it uses a memory return, and if we are at the first
+ // instruction and if so stash away the return location. Then we would
// only return the memory return value if we know it is valid.
unsigned r2_id =
@@ -654,8 +653,8 @@ bool ABISysV_s390x::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
}
bool ABISysV_s390x::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
- // There's really no default way to unwind on s390x.
- // Trust the .eh_frame CFI, which should always be good.
+ // There's really no default way to unwind on s390x. Trust the .eh_frame CFI,
+ // which should always be good.
return false;
}
@@ -663,8 +662,8 @@ bool ABISysV_s390x::GetFallbackRegisterLocation(
const RegisterInfo *reg_info,
UnwindPlan::Row::RegisterLocation &unwind_regloc) {
// If a volatile register is being requested, we don't want to forward the
- // next frame's register contents
- // up the stack -- the register is not retrievable at this frame.
+ // next frame's register contents up the stack -- the register is not
+ // retrievable at this frame.
if (RegisterIsVolatile(reg_info)) {
unwind_regloc.SetUndefined();
return true;
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 41d146f24526..36ae3a49827c 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -1267,8 +1267,8 @@ bool ABISysV_x86_64::GetArgumentValues(Thread &thread,
if (!value)
return false;
- // We currently only support extracting values with Clang QualTypes.
- // Do we care about others?
+ // We currently only support extracting values with Clang QualTypes. Do we
+ // care about others?
CompilerType compiler_type = value->GetCompilerType();
if (!compiler_type)
return false;
@@ -1371,8 +1371,8 @@ Status ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
if (!set_it_simple) {
// Okay we've got a structure or something that doesn't fit in a simple
- // register.
- // We should figure out where it really goes, but we don't support this yet.
+ // register. We should figure out where it really goes, but we don't
+ // support this yet.
error.SetErrorString("We only support setting simple integer and float "
"return types at present.");
}
@@ -1624,8 +1624,8 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
idx, name, &field_bit_offset, nullptr, nullptr);
const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
- // if we don't know the size of the field (e.g. invalid type), just bail
- // out
+ // if we don't know the size of the field (e.g. invalid type), just
+ // bail out
if (field_bit_width == 0)
break;
@@ -1661,10 +1661,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
copy_from_offset = integer_bytes - 8;
integer_bytes += field_byte_width;
} else {
- // The last field didn't fit. I can't see how that would happen w/o
- // the overall size being
- // greater than 16 bytes. For now, return a nullptr return value
- // object.
+ // The last field didn't fit. I can't see how that would happen
+ // w/o the overall size being greater than 16 bytes. For now,
+ // return a nullptr return value object.
return return_valobj_sp;
}
} else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
@@ -1683,10 +1682,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
fp_bytes += field_byte_width;
} else if (field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
- // with another float, we'll
- // be stuffed into an xmm register with it. If we are in an
- // "eightbyte" with one or more ints,
- // then we will be stuffed into the appropriate GPR with them.
+ // with another float, we'll be stuffed into an xmm register with
+ // it. If we are in an "eightbyte" with one or more ints, then we
+ // will be stuffed into the appropriate GPR with them.
bool in_gpr;
if (field_byte_offset % 8 == 0) {
// We are at the beginning of one of the eightbytes, so check the
@@ -1708,9 +1706,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
}
}
} else if (field_byte_offset % 4 == 0) {
- // We are inside of an eightbyte, so see if the field before us is
- // floating point:
- // This could happen if somebody put padding in the structure.
+ // We are inside of an eightbyte, so see if the field before us
+ // is floating point: This could happen if somebody put padding
+ // in the structure.
if (idx == 0)
in_gpr = false;
else {
@@ -1756,9 +1754,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
}
}
- // These two tests are just sanity checks. If I somehow get the
- // type calculation wrong above it is better to just return nothing
- // than to assert or crash.
+ // These two tests are just sanity checks. If I somehow get the type
+ // calculation wrong above it is better to just return nothing than to
+ // assert or crash.
if (!copy_from_extractor)
return return_valobj_sp;
if (copy_from_offset + field_byte_width >
@@ -1782,9 +1780,8 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
// FIXME: This is just taking a guess, rax may very well no longer hold the
// return storage location.
// If we are going to do this right, when we make a new frame we should
- // check to see if it uses a memory
- // return, and if we are at the first instruction and if so stash away the
- // return location. Then we would
+ // check to see if it uses a memory return, and if we are at the first
+ // instruction and if so stash away the return location. Then we would
// only return the memory return value if we know it is valid.
if (is_memory) {
@@ -1858,12 +1855,11 @@ bool ABISysV_x86_64::RegisterIsVolatile(const RegisterInfo *reg_info) {
// See "Register Usage" in the
// "System V Application Binary Interface"
-// "AMD64 Architecture Processor Supplement"
-// (or "x86-64(tm) Architecture Processor Supplement" in earlier revisions)
-// (this doc is also commonly referred to as the x86-64/AMD64 psABI)
-// Edited by Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
-// current version is 0.99.6 released 2012-07-02 at
-// http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf
+// "AMD64 Architecture Processor Supplement" (or "x86-64(tm) Architecture
+// Processor Supplement" in earlier revisions) (this doc is also commonly
+// referred to as the x86-64/AMD64 psABI) Edited by Michael Matz, Jan Hubicka,
+// Andreas Jaeger, and Mark Mitchell current version is 0.99.6 released
+// 2012-07-02 at http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf
// It's being revised & updated at https://github.com/hjl-tools/x86-psABI/
bool ABISysV_x86_64::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.cpp b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
index abac6d3001af..1b7ecc88c35e 100644
--- a/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
+++ b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
@@ -41,32 +41,32 @@ std::unique_ptr<Architecture> ArchitectureArm::Create(const ArchSpec &arch) {
ConstString ArchitectureArm::GetPluginName() { return GetPluginNameStatic(); }
uint32_t ArchitectureArm::GetPluginVersion() { return 1; }
-void ArchitectureArm::OverrideStopInfo(Thread &thread) {
- // We need to check if we are stopped in Thumb mode in a IT instruction
- // and detect if the condition doesn't pass. If this is the case it means
- // we won't actually execute this instruction. If this happens we need to
- // clear the stop reason to no thread plans think we are stopped for a
- // reason and the plans should keep going.
+void ArchitectureArm::OverrideStopInfo(Thread &thread) const {
+ // We need to check if we are stopped in Thumb mode in a IT instruction and
+ // detect if the condition doesn't pass. If this is the case it means we
+ // won't actually execute this instruction. If this happens we need to clear
+ // the stop reason to no thread plans think we are stopped for a reason and
+ // the plans should keep going.
//
// We do this because when single stepping many ARM processes, debuggers
- // often use the BVR/BCR registers that says "stop when the PC is not
- // equal to its current value". This method of stepping means we can end
- // up stopping on instructions inside an if/then block that wouldn't get
- // executed. By fixing this we can stop the debugger from seeming like
- // you stepped through both the "if" _and_ the "else" clause when source
- // level stepping because the debugger stops regardless due to the BVR/BCR
+ // often use the BVR/BCR registers that says "stop when the PC is not equal
+ // to its current value". This method of stepping means we can end up
+ // stopping on instructions inside an if/then block that wouldn't get
+ // executed. By fixing this we can stop the debugger from seeming like you
+ // stepped through both the "if" _and_ the "else" clause when source level
+ // stepping because the debugger stops regardless due to the BVR/BCR
// triggering a stop.
//
- // It also means we can set breakpoints on instructions inside an an
- // if/then block and correctly skip them if we use the BKPT instruction.
- // The ARM and Thumb BKPT instructions are unconditional even when executed
- // in a Thumb IT block.
+ // It also means we can set breakpoints on instructions inside an an if/then
+ // block and correctly skip them if we use the BKPT instruction. The ARM and
+ // Thumb BKPT instructions are unconditional even when executed in a Thumb IT
+ // block.
//
- // If your debugger inserts software traps in ARM/Thumb code, it will
- // need to use 16 and 32 bit instruction for 16 and 32 bit thumb
- // instructions respectively. If your debugger inserts a 16 bit thumb
- // trap on top of a 32 bit thumb instruction for an opcode that is inside
- // an if/then, it will change the it/then to conditionally execute your
+ // If your debugger inserts software traps in ARM/Thumb code, it will need to
+ // use 16 and 32 bit instruction for 16 and 32 bit thumb instructions
+ // respectively. If your debugger inserts a 16 bit thumb trap on top of a 32
+ // bit thumb instruction for an opcode that is inside an if/then, it will
+ // change the it/then to conditionally execute your
// 16 bit trap and then cause your program to crash if it executes the
// trailing 16 bits (the second half of the 32 bit thumb instruction you
// partially overwrote).
@@ -85,23 +85,20 @@ void ArchitectureArm::OverrideStopInfo(Thread &thread) {
const uint32_t ISETSTATE = J << 1 | T;
if (ISETSTATE == 0) {
// NOTE: I am pretty sure we want to enable the code below
-// that detects when we stop on an instruction in ARM mode
-// that is conditional and the condition doesn't pass. This
-// can happen if you set a breakpoint on an instruction that
-// is conditional. We currently will _always_ stop on the
-// instruction which is bad. You can also run into this while
-// single stepping and you could appear to run code in the "if"
-// and in the "else" clause because it would stop at all of the
-// conditional instructions in both.
-// In such cases, we really don't want to stop at this location.
+// that detects when we stop on an instruction in ARM mode that is conditional
+// and the condition doesn't pass. This can happen if you set a breakpoint on
+// an instruction that is conditional. We currently will _always_ stop on the
+// instruction which is bad. You can also run into this while single stepping
+// and you could appear to run code in the "if" and in the "else" clause
+// because it would stop at all of the conditional instructions in both. In
+// such cases, we really don't want to stop at this location.
// I will check with the lldb-dev list first before I enable this.
#if 0
- // ARM mode: check for condition on intsruction
+ // ARM mode: check for condition on instruction
const addr_t pc = reg_ctx_sp->GetPC();
Status error;
- // If we fail to read the opcode we will get UINT64_MAX as the
- // result in "opcode" which we can use to detect if we read a
- // valid opcode.
+ // If we fail to read the opcode we will get UINT64_MAX as the result in
+ // "opcode" which we can use to detect if we read a valid opcode.
const uint64_t opcode = thread.GetProcess()->ReadUnsignedIntegerFromMemory(pc, 4, UINT64_MAX, error);
if (opcode <= UINT32_MAX)
{
@@ -109,8 +106,8 @@ void ArchitectureArm::OverrideStopInfo(Thread &thread) {
if (!ARMConditionPassed(condition, cpsr))
{
// We ARE stopped on an ARM instruction whose condition doesn't
- // pass so this instruction won't get executed.
- // Regardless of why it stopped, we need to clear the stop info
+ // pass so this instruction won't get executed. Regardless of why
+ // it stopped, we need to clear the stop info
thread.SetStopInfo (StopInfoSP());
}
}
diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.h b/source/Plugins/Architecture/Arm/ArchitectureArm.h
index 9ce6c69ef271..484c4a52fcc6 100644
--- a/source/Plugins/Architecture/Arm/ArchitectureArm.h
+++ b/source/Plugins/Architecture/Arm/ArchitectureArm.h
@@ -23,7 +23,7 @@ public:
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
- void OverrideStopInfo(Thread &thread) override;
+ void OverrideStopInfo(Thread &thread) const override;
private:
static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
diff --git a/source/Plugins/Architecture/CMakeLists.txt b/source/Plugins/Architecture/CMakeLists.txt
index 5abaa8e68231..01365a64cf96 100644
--- a/source/Plugins/Architecture/CMakeLists.txt
+++ b/source/Plugins/Architecture/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(Arm)
+add_subdirectory(PPC64)
diff --git a/source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp b/source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp
new file mode 100644
index 000000000000..619de093aacc
--- /dev/null
+++ b/source/Plugins/Architecture/PPC64/ArchitecturePPC64.cpp
@@ -0,0 +1,69 @@
+//===-- ArchitecturePPC64.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/ArchSpec.h"
+
+#include "llvm/BinaryFormat/ELF.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+ConstString ArchitecturePPC64::GetPluginNameStatic() {
+ return ConstString("ppc64");
+}
+
+void ArchitecturePPC64::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "PPC64-specific algorithms",
+ &ArchitecturePPC64::Create);
+}
+
+void ArchitecturePPC64::Terminate() {
+ PluginManager::UnregisterPlugin(&ArchitecturePPC64::Create);
+}
+
+std::unique_ptr<Architecture> ArchitecturePPC64::Create(const ArchSpec &arch) {
+ if ((arch.GetMachine() != llvm::Triple::ppc64 &&
+ arch.GetMachine() != llvm::Triple::ppc64le) ||
+ arch.GetTriple().getObjectFormat() != llvm::Triple::ObjectFormatType::ELF)
+ return nullptr;
+ return std::unique_ptr<Architecture>(new ArchitecturePPC64());
+}
+
+ConstString ArchitecturePPC64::GetPluginName() { return GetPluginNameStatic(); }
+uint32_t ArchitecturePPC64::GetPluginVersion() { return 1; }
+
+static int32_t GetLocalEntryOffset(const Symbol &sym) {
+ unsigned char other = sym.GetFlags() >> 8 & 0xFF;
+ return llvm::ELF::decodePPC64LocalEntryOffset(other);
+}
+
+size_t ArchitecturePPC64::GetBytesToSkip(Symbol &func,
+ const Address &curr_addr) const {
+ if (curr_addr.GetFileAddress() ==
+ func.GetFileAddress() + GetLocalEntryOffset(func))
+ return func.GetPrologueByteSize();
+ return 0;
+}
+
+void ArchitecturePPC64::AdjustBreakpointAddress(const Symbol &func,
+ Address &addr) const {
+ int32_t loffs = GetLocalEntryOffset(func);
+ if (!loffs)
+ return;
+
+ addr.SetOffset(addr.GetOffset() + loffs);
+}
diff --git a/source/Plugins/Architecture/PPC64/ArchitecturePPC64.h b/source/Plugins/Architecture/PPC64/ArchitecturePPC64.h
new file mode 100644
index 000000000000..95638853ad3d
--- /dev/null
+++ b/source/Plugins/Architecture/PPC64/ArchitecturePPC64.h
@@ -0,0 +1,44 @@
+//===-- ArchitecturePPC64.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGIN_ARCHITECTURE_PPC64_H
+#define LLDB_PLUGIN_ARCHITECTURE_PPC64_H
+
+#include "lldb/Core/Architecture.h"
+
+namespace lldb_private {
+
+class ArchitecturePPC64 : public Architecture {
+public:
+ static ConstString GetPluginNameStatic();
+ static void Initialize();
+ static void Terminate();
+
+ ConstString GetPluginName() override;
+ uint32_t GetPluginVersion() override;
+
+ void OverrideStopInfo(Thread &thread) const override {}
+
+ //------------------------------------------------------------------
+ /// This method compares current address with current function's
+ /// local entry point, returning the bytes to skip if they match.
+ //------------------------------------------------------------------
+ size_t GetBytesToSkip(Symbol &func, const Address &curr_addr) const override;
+
+ void AdjustBreakpointAddress(const Symbol &func,
+ Address &addr) const override;
+
+private:
+ static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
+ ArchitecturePPC64() = default;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_PLUGIN_ARCHITECTURE_PPC64_H
diff --git a/source/Plugins/Architecture/PPC64/CMakeLists.txt b/source/Plugins/Architecture/PPC64/CMakeLists.txt
new file mode 100644
index 000000000000..2cba112cf882
--- /dev/null
+++ b/source/Plugins/Architecture/PPC64/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginArchitecturePPC64 PLUGIN
+ ArchitecturePPC64.cpp
+
+ LINK_LIBS
+ lldbPluginProcessUtility
+ lldbCore
+ lldbTarget
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index a61abb9898ac..9b381dd3b96c 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -10,6 +10,9 @@
// C Includes
// C++ Includes
// Project includes
+#include "DisassemblerLLVMC.h"
+
+// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -27,9 +30,6 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
-// Other libraries and framework includes
-#include "DisassemblerLLVMC.h"
-
#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -41,13 +41,47 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Stream.h"
-
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Stream.h"
using namespace lldb;
using namespace lldb_private;
+class DisassemblerLLVMC::MCDisasmInstance {
+public:
+ static std::unique_ptr<MCDisasmInstance>
+ Create(const char *triple, const char *cpu, const char *features_str,
+ unsigned flavor, DisassemblerLLVMC &owner);
+
+ ~MCDisasmInstance() = default;
+
+ uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len,
+ lldb::addr_t pc, llvm::MCInst &mc_inst) const;
+ 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) const;
+ bool HasDelaySlot(llvm::MCInst &mc_inst) const;
+ bool IsCall(llvm::MCInst &mc_inst) const;
+
+private:
+ MCDisasmInstance(std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
+ std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
+ std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
+ std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
+ std::unique_ptr<llvm::MCContext> &&context_up,
+ std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
+ std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up);
+
+ std::unique_ptr<llvm::MCInstrInfo> m_instr_info_up;
+ std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_up;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_up;
+ std::unique_ptr<llvm::MCAsmInfo> m_asm_info_up;
+ std::unique_ptr<llvm::MCContext> m_context_up;
+ std::unique_ptr<llvm::MCDisassembler> m_disasm_up;
+ std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_up;
+};
+
class InstructionLLVMC : public lldb_private::Instruction {
public:
InstructionLLVMC(DisassemblerLLVMC &disasm,
@@ -72,7 +106,7 @@ public:
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
@@ -107,7 +141,7 @@ public:
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
@@ -132,19 +166,19 @@ public:
return m_has_delay_slot == eLazyBoolYes;
}
- DisassemblerLLVMC::LLVMCDisassembler *GetDisasmToUse(bool &is_alternate_isa) {
+ DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) {
is_alternate_isa = false;
std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
if (disasm_sp) {
- if (disasm_sp->m_alternate_disasm_ap.get() != NULL) {
+ if (disasm_sp->m_alternate_disasm_up) {
const AddressClass address_class = GetAddressClass();
- if (address_class == eAddressClassCodeAlternateISA) {
+ if (address_class == AddressClass::eCodeAlternateISA) {
is_alternate_isa = true;
- return disasm_sp->m_alternate_disasm_ap.get();
+ return disasm_sp->m_alternate_disasm_up.get();
}
}
- return disasm_sp->m_disasm_ap.get();
+ return disasm_sp->m_disasm_up.get();
}
return nullptr;
}
@@ -197,7 +231,7 @@ public:
}
if (!got_op) {
bool is_alternate_isa = false;
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const llvm::Triple::ArchType machine = arch.GetMachine();
@@ -264,12 +298,12 @@ public:
std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
if (disasm_sp) {
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr;
- if (address_class == eAddressClassCodeAlternateISA)
- mc_disasm_ptr = disasm_sp->m_alternate_disasm_ap.get();
+ if (address_class == AddressClass::eCodeAlternateISA)
+ mc_disasm_ptr = disasm_sp->m_alternate_disasm_up.get();
else
- mc_disasm_ptr = disasm_sp->m_disasm_ap.get();
+ mc_disasm_ptr = disasm_sp->m_disasm_up.get();
lldb::addr_t pc = m_address.GetFileAddress();
m_using_file_addr = true;
@@ -850,7 +884,7 @@ public:
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
- DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr =
+ DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
GetDisasmToUse(is_alternate_isa);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
@@ -881,80 +915,103 @@ protected:
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) {
+std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>
+DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu,
+ const char *features_str,
+ unsigned flavor,
+ DisassemblerLLVMC &owner) {
+ using Instance = std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>;
+
std::string Status;
const llvm::Target *curr_target =
llvm::TargetRegistry::lookupTarget(triple, Status);
- if (!curr_target) {
- m_is_valid = false;
- return;
- }
+ if (!curr_target)
+ return Instance();
- m_instr_info_ap.reset(curr_target->createMCInstrInfo());
- m_reg_info_ap.reset(curr_target->createMCRegInfo(triple));
-
- m_subtarget_info_ap.reset(
- curr_target->createMCSubtargetInfo(triple, cpu, features_str));
+ std::unique_ptr<llvm::MCInstrInfo> instr_info_up(
+ curr_target->createMCInstrInfo());
+ if (!instr_info_up)
+ return Instance();
- std::unique_ptr<llvm::MCRegisterInfo> reg_info(
+ std::unique_ptr<llvm::MCRegisterInfo> reg_info_up(
curr_target->createMCRegInfo(triple));
- m_asm_info_ap.reset(curr_target->createMCAsmInfo(*reg_info, triple));
+ if (!reg_info_up)
+ return Instance();
- if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL ||
- m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL) {
- m_is_valid = false;
- return;
- }
-
- m_context_ap.reset(
- new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0));
-
- m_disasm_ap.reset(curr_target->createMCDisassembler(
- *m_subtarget_info_ap.get(), *m_context_ap.get()));
- if (m_disasm_ap.get() && m_context_ap.get()) {
- std::unique_ptr<llvm::MCRelocationInfo> RelInfo(
- curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
- if (!RelInfo) {
- m_is_valid = false;
- return;
- }
- std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(
- curr_target->createMCSymbolizer(
- triple, NULL, DisassemblerLLVMC::SymbolLookupCallback,
- (void *)&owner, m_context_ap.get(), std::move(RelInfo)));
- m_disasm_ap->setSymbolizer(std::move(symbolizer_up));
-
- unsigned asm_printer_variant;
- if (flavor == ~0U)
- asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
- else {
- asm_printer_variant = flavor;
- }
-
- m_instr_printer_ap.reset(curr_target->createMCInstPrinter(
- llvm::Triple{triple}, asm_printer_variant, *m_asm_info_ap.get(),
- *m_instr_info_ap.get(), *m_reg_info_ap.get()));
- if (m_instr_printer_ap.get() == NULL) {
- m_disasm_ap.reset();
- m_is_valid = false;
- }
- } else
- m_is_valid = false;
+ std::unique_ptr<llvm::MCSubtargetInfo> subtarget_info_up(
+ curr_target->createMCSubtargetInfo(triple, cpu, features_str));
+ if (!subtarget_info_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCAsmInfo> asm_info_up(
+ curr_target->createMCAsmInfo(*reg_info_up, triple));
+ if (!asm_info_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCContext> context_up(
+ new llvm::MCContext(asm_info_up.get(), reg_info_up.get(), 0));
+ if (!context_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCDisassembler> disasm_up(
+ curr_target->createMCDisassembler(*subtarget_info_up, *context_up));
+ if (!disasm_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCRelocationInfo> rel_info_up(
+ curr_target->createMCRelocationInfo(triple, *context_up));
+ if (!rel_info_up)
+ return Instance();
+
+ std::unique_ptr<llvm::MCSymbolizer> symbolizer_up(
+ curr_target->createMCSymbolizer(
+ triple, nullptr, DisassemblerLLVMC::SymbolLookupCallback, &owner,
+ context_up.get(), std::move(rel_info_up)));
+ disasm_up->setSymbolizer(std::move(symbolizer_up));
+
+ unsigned asm_printer_variant =
+ flavor == ~0U ? asm_info_up->getAssemblerDialect() : flavor;
+
+ std::unique_ptr<llvm::MCInstPrinter> instr_printer_up(
+ curr_target->createMCInstPrinter(llvm::Triple{triple},
+ asm_printer_variant, *asm_info_up,
+ *instr_info_up, *reg_info_up));
+ if (!instr_printer_up)
+ return Instance();
+
+ return Instance(
+ new MCDisasmInstance(std::move(instr_info_up), std::move(reg_info_up),
+ std::move(subtarget_info_up), std::move(asm_info_up),
+ std::move(context_up), std::move(disasm_up),
+ std::move(instr_printer_up)));
}
-DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default;
+DisassemblerLLVMC::MCDisasmInstance::MCDisasmInstance(
+ std::unique_ptr<llvm::MCInstrInfo> &&instr_info_up,
+ std::unique_ptr<llvm::MCRegisterInfo> &&reg_info_up,
+ std::unique_ptr<llvm::MCSubtargetInfo> &&subtarget_info_up,
+ std::unique_ptr<llvm::MCAsmInfo> &&asm_info_up,
+ std::unique_ptr<llvm::MCContext> &&context_up,
+ std::unique_ptr<llvm::MCDisassembler> &&disasm_up,
+ std::unique_ptr<llvm::MCInstPrinter> &&instr_printer_up)
+ : m_instr_info_up(std::move(instr_info_up)),
+ m_reg_info_up(std::move(reg_info_up)),
+ m_subtarget_info_up(std::move(subtarget_info_up)),
+ m_asm_info_up(std::move(asm_info_up)),
+ m_context_up(std::move(context_up)), m_disasm_up(std::move(disasm_up)),
+ m_instr_printer_up(std::move(instr_printer_up)) {
+ assert(m_instr_info_up && m_reg_info_up && m_subtarget_info_up &&
+ m_asm_info_up && m_context_up && m_disasm_up && m_instr_printer_up);
+}
-uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst(
+uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst(
const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc,
- llvm::MCInst &mc_inst) {
+ llvm::MCInst &mc_inst) const {
llvm::ArrayRef<uint8_t> data(opcode_data, opcode_data_len);
llvm::MCDisassembler::DecodeStatus status;
uint64_t new_inst_size;
- status = m_disasm_ap->getInstruction(mc_inst, new_inst_size, data, pc,
+ status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc,
llvm::nulls(), llvm::nulls());
if (status == llvm::MCDisassembler::Success)
return new_inst_size;
@@ -962,16 +1019,16 @@ uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst(
return 0;
}
-void DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst(
+void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst(
llvm::MCInst &mc_inst, std::string &inst_string,
std::string &comments_string) {
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());
+ m_instr_printer_up->setCommentStream(comments_stream);
+ m_instr_printer_up->printInst(&mc_inst, inst_stream, llvm::StringRef(),
+ *m_subtarget_info_up);
+ m_instr_printer_up->setCommentStream(llvm::nulls());
comments_stream.flush();
static std::string g_newlines("\r\n");
@@ -985,30 +1042,32 @@ void DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst(
}
}
-void DisassemblerLLVMC::LLVMCDisassembler::SetStyle(
+void DisassemblerLLVMC::MCDisasmInstance::SetStyle(
bool use_hex_immed, HexImmediateStyle hex_style) {
- m_instr_printer_ap->setPrintImmHex(use_hex_immed);
+ m_instr_printer_up->setPrintImmHex(use_hex_immed);
switch (hex_style) {
case eHexStyleC:
- m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::C);
+ m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::C);
break;
case eHexStyleAsm:
- m_instr_printer_ap->setPrintHexStyle(llvm::HexStyle::Asm);
+ m_instr_printer_up->setPrintHexStyle(llvm::HexStyle::Asm);
break;
}
}
-bool DisassemblerLLVMC::LLVMCDisassembler::CanBranch(llvm::MCInst &mc_inst) {
- return m_instr_info_ap->get(mc_inst.getOpcode())
- .mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
+bool DisassemblerLLVMC::MCDisasmInstance::CanBranch(
+ llvm::MCInst &mc_inst) const {
+ return m_instr_info_up->get(mc_inst.getOpcode())
+ .mayAffectControlFlow(mc_inst, *m_reg_info_up);
}
-bool DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot(llvm::MCInst &mc_inst) {
- return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot();
+bool DisassemblerLLVMC::MCDisasmInstance::HasDelaySlot(
+ llvm::MCInst &mc_inst) const {
+ return m_instr_info_up->get(mc_inst.getOpcode()).hasDelaySlot();
}
-bool DisassemblerLLVMC::LLVMCDisassembler::IsCall(llvm::MCInst &mc_inst) {
- return m_instr_info_ap->get(mc_inst.getOpcode()).isCall();
+bool DisassemblerLLVMC::MCDisasmInstance::IsCall(llvm::MCInst &mc_inst) const {
+ return m_instr_info_up->get(mc_inst.getOpcode()).isCall();
}
DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
@@ -1023,8 +1082,7 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
llvm::Triple triple = arch.GetTriple();
// So far the only supported flavor is "intel" on x86. The base class will
- // set this
- // correctly coming in.
+ // set this correctly coming in.
if (triple.getArch() == llvm::Triple::x86 ||
triple.getArch() == llvm::Triple::x86_64) {
if (m_flavor == "intel") {
@@ -1048,12 +1106,10 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
}
// 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)
+ // 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.2a");
@@ -1127,20 +1183,16 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
features_str += "+dspr2,";
}
- // If any AArch64 variant, enable the ARMv8.2 ISA
- // extensions so we can disassemble newer instructions.
+ // If any AArch64 variant, enable the ARMv8.2 ISA extensions so we can
+ // disassemble newer instructions.
if (triple.getArch() == llvm::Triple::aarch64)
features_str += "+v8.2a";
- 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,
- // we reset it, and then we won't be valid and FindPlugin will fail and we
- // won't get used.
- m_disasm_ap.reset();
- }
+ // We use m_disasm_ap.get() to tell whether we are valid or not, so if this
+ // isn't good for some reason, we won't be valid and FindPlugin will fail and
+ // we won't get used.
+ m_disasm_up = MCDisasmInstance::Create(triple_str, cpu, features_str.c_str(),
+ flavor, *this);
llvm::Triple::ArchType llvm_arch = triple.getArch();
@@ -1148,12 +1200,11 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
// thumb instruction disassembler.
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));
- if (!m_alternate_disasm_ap->IsValid()) {
- m_disasm_ap.reset();
- m_alternate_disasm_ap.reset();
- }
+ m_alternate_disasm_up =
+ MCDisasmInstance::Create(thumb_triple.c_str(), "", "", flavor, *this);
+ if (!m_alternate_disasm_up)
+ m_disasm_up.reset();
+
} else if (llvm_arch == llvm::Triple::mips ||
llvm_arch == llvm::Triple::mipsel ||
llvm_arch == llvm::Triple::mips64 ||
@@ -1165,12 +1216,10 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
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();
- }
+ m_alternate_disasm_up = MCDisasmInstance::Create(
+ triple_str, cpu, features_str.c_str(), flavor, *this);
+ if (!m_alternate_disasm_up)
+ m_disasm_up.reset();
}
}
@@ -1208,9 +1257,9 @@ size_t DisassemblerLLVMC::DecodeInstructions(const Address &base_addr,
while (data_cursor < data_byte_size &&
instructions_parsed < num_instructions) {
- AddressClass address_class = eAddressClassCode;
+ AddressClass address_class = AddressClass::eCode;
- if (m_alternate_disasm_ap.get() != NULL)
+ if (m_alternate_disasm_up)
address_class = inst_addr.GetAddressClass();
InstructionSP inst_sp(
@@ -1285,6 +1334,8 @@ bool DisassemblerLLVMC::FlavorValidForArchSpec(
return false;
}
+bool DisassemblerLLVMC::IsValid() const { return m_disasm_up.operator bool(); }
+
int DisassemblerLLVMC::OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size,
int tag_type, void *tag_bug) {
switch (tag_type) {
@@ -1337,8 +1388,8 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
}
}
- // If the "value" address (the target address we're symbolicating)
- // is inside the same SymbolContext as the current instruction pc
+ // If the "value" address (the target address we're symbolicating) is
+ // inside the same SymbolContext as the current instruction pc
// (pc_so_addr), don't print the full function name - just print it
// with DumpStyleNoFunctionName style, e.g. "<+36>".
if (format_omitting_current_func_name) {
@@ -1353,9 +1404,8 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
if (!ss.GetString().empty()) {
// If Address::Dump returned a multi-line description, most commonly
- // seen when we
- // have multiple levels of inlined functions at an address, only show
- // the first line.
+ // seen when we have multiple levels of inlined functions at an
+ // address, only show the first line.
std::string str = ss.GetString();
size_t first_eol_char = str.find_first_of("\r\n");
if (first_eol_char != std::string::npos) {
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index 26bed7ee0d7b..b7e9ccb34701 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -16,62 +16,14 @@
#include <mutex>
#include <string>
-// Other libraries and framework includes
-#include "llvm-c/Disassembler.h"
-
// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/PluginManager.h"
-// Opaque references to C++ Objects in LLVM's MC.
-namespace llvm {
-class MCContext;
-class MCInst;
-class MCInstrInfo;
-class MCRegisterInfo;
-class MCDisassembler;
-class MCInstPrinter;
-class MCAsmInfo;
-class MCSubtargetInfo;
-} // namespace llvm
-
class InstructionLLVMC;
class DisassemblerLLVMC : public lldb_private::Disassembler {
- // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB),
- // and there's a bit of goo to set up and own
- // in the MC disassembler world, I added this class to manage the actual
- // disassemblers.
- class LLVMCDisassembler {
- public:
- LLVMCDisassembler(const char *triple, const char *cpu,
- const char *features_str, unsigned flavor,
- DisassemblerLLVMC &owner);
-
- ~LLVMCDisassembler();
-
- uint64_t GetMCInst(const uint8_t *opcode_data, size_t opcode_data_len,
- lldb::addr_t pc, llvm::MCInst &mc_inst);
- 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 IsCall(llvm::MCInst &mc_inst);
- bool IsValid() { return m_is_valid; }
-
- private:
- bool m_is_valid;
- std::unique_ptr<llvm::MCContext> m_context_ap;
- std::unique_ptr<llvm::MCAsmInfo> m_asm_info_ap;
- std::unique_ptr<llvm::MCSubtargetInfo> m_subtarget_info_ap;
- std::unique_ptr<llvm::MCInstrInfo> m_instr_info_ap;
- std::unique_ptr<llvm::MCRegisterInfo> m_reg_info_ap;
- std::unique_ptr<llvm::MCInstPrinter> m_instr_printer_ap;
- std::unique_ptr<llvm::MCDisassembler> m_disasm_ap;
- };
-
public:
DisassemblerLLVMC(const lldb_private::ArchSpec &arch,
const char *flavor /* = NULL */);
@@ -108,9 +60,7 @@ protected:
bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch,
const char *flavor) override;
- bool IsValid() {
- return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid());
- }
+ bool IsValid() const;
int OpInfo(uint64_t PC, uint64_t Offset, uint64_t Size, int TagType,
void *TagBug);
@@ -145,8 +95,12 @@ protected:
std::mutex m_mutex;
bool m_data_from_file;
- std::unique_ptr<LLVMCDisassembler> m_disasm_ap;
- std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
+ // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB),
+ // and there's a bit of goo to set up and own in the MC disassembler world,
+ // this class was added to manage the actual disassemblers.
+ class MCDisasmInstance;
+ std::unique_ptr<MCDisasmInstance> m_disasm_up;
+ std::unique_ptr<MCDisasmInstance> m_alternate_disasm_up;
};
#endif // liblldb_DisassemblerLLVM_h_
diff --git a/source/Plugins/DynamicLoader/CMakeLists.txt b/source/Plugins/DynamicLoader/CMakeLists.txt
index 8e1b316a3c25..9f3b2ab0e50f 100644
--- a/source/Plugins/DynamicLoader/CMakeLists.txt
+++ b/source/Plugins/DynamicLoader/CMakeLists.txt
@@ -1,9 +1,6 @@
+add_subdirectory(Darwin-Kernel)
add_subdirectory(MacOSX-DYLD)
add_subdirectory(POSIX-DYLD)
add_subdirectory(Static)
add_subdirectory(Hexagon-DYLD)
add_subdirectory(Windows-DYLD)
-
-if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
- add_subdirectory(Darwin-Kernel)
-endif()
diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index a81a0306671e..8999000dff8c 100644
--- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -8,8 +8,6 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Utility/SafeMachO.h"
-
#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
@@ -45,10 +43,10 @@
using namespace lldb;
using namespace lldb_private;
-// Progressively greater amounts of scanning we will allow
-// For some targets very early in startup, we can't do any random reads of
-// memory or we can crash the device
-// so a setting is needed that can completely disable the KASLR scans.
+// Progressively greater amounts of scanning we will allow For some targets
+// very early in startup, we can't do any random reads of memory or we can
+// crash the device so a setting is needed that can completely disable the
+// KASLR scans.
enum KASLRScanType {
eKASLRScanNone = 0, // No reading into the inferior at all
@@ -122,15 +120,15 @@ static const DynamicLoaderDarwinKernelPropertiesSP &GetGlobalProperties() {
}
//----------------------------------------------------------------------
-// Create an instance of this class. This function is filled into
-// the plugin info class that gets handed out by the plugin factory and
-// allows the lldb to instantiate an instance of this class.
+// Create an instance of this class. This function is filled into the plugin
+// info class that gets handed out by the plugin factory and allows the lldb to
+// instantiate an instance of this class.
//----------------------------------------------------------------------
DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process,
bool force) {
if (!force) {
- // If the user provided an executable binary and it is not a kernel,
- // this plugin should not create an instance.
+ // If the user provided an executable binary and it is not a kernel, this
+ // plugin should not create an instance.
Module *exe_module = process->GetTarget().GetExecutableModulePointer();
if (exe_module) {
ObjectFile *object_file = exe_module->GetObjectFile();
@@ -155,8 +153,8 @@ DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process,
return NULL;
}
break;
- // If we have triple like armv7-unknown-unknown, we should try looking for a
- // Darwin kernel.
+ // If we have triple like armv7-unknown-unknown, we should try looking for
+ // a Darwin kernel.
case llvm::Triple::UnknownOS:
break;
default:
@@ -166,9 +164,8 @@ DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process,
}
// At this point if there is an ExecutableModule, it is a kernel and the
- // Target is some variant of an Apple system.
- // If the Process hasn't provided the kernel load address, we need to look
- // around in memory to find it.
+ // Target is some variant of an Apple system. If the Process hasn't provided
+ // the kernel load address, we need to look around in memory to find it.
const addr_t kernel_load_address = SearchForDarwinKernel(process);
if (CheckForKernelImageAtAddress(kernel_load_address, process).IsValid()) {
@@ -197,10 +194,9 @@ DynamicLoaderDarwinKernel::SearchForDarwinKernel(Process *process) {
}
//----------------------------------------------------------------------
-// Check if the kernel binary is loaded in memory without a slide.
-// First verify that the ExecutableModule is a kernel before we proceed.
-// Returns the address of the kernel if one was found, else
-// LLDB_INVALID_ADDRESS.
+// Check if the kernel binary is loaded in memory without a slide. First verify
+// that the ExecutableModule is a kernel before we proceed. Returns the address
+// of the kernel if one was found, else LLDB_INVALID_ADDRESS.
//----------------------------------------------------------------------
lldb::addr_t
DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr(Process *process) {
@@ -229,10 +225,8 @@ DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr(Process *process) {
//----------------------------------------------------------------------
// If the debug flag is included in the boot-args nvram setting, the kernel's
-// load address
-// will be noted in the lowglo page at a fixed address
-// Returns the address of the kernel if one was found, else
-// LLDB_INVALID_ADDRESS.
+// load address will be noted in the lowglo page at a fixed address Returns the
+// address of the kernel if one was found, else LLDB_INVALID_ADDRESS.
//----------------------------------------------------------------------
lldb::addr_t
DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) {
@@ -282,8 +276,8 @@ DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints(Process *process) {
}
//----------------------------------------------------------------------
-// If the kernel is currently executing when lldb attaches, and we don't have
-// a better way of finding the kernel's load address, try searching backwards
+// If the kernel is currently executing when lldb attaches, and we don't have a
+// better way of finding the kernel's load address, try searching backwards
// from the current pc value looking for the kernel's Mach header in memory.
// Returns the address of the kernel if one was found, else
// LLDB_INVALID_ADDRESS.
@@ -304,9 +298,8 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) {
return LLDB_INVALID_ADDRESS;
// The kernel will load at at one megabyte boundary (0x100000), or at that
- // boundary plus
- // an offset of one page (0x1000) or two, or four (0x4000), depending on the
- // device.
+ // boundary plus an offset of one page (0x1000) or two, or four (0x4000),
+ // depending on the device.
// Round the current pc down to the nearest one megabyte boundary - the place
// where we will start searching.
@@ -329,11 +322,10 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) {
}
//----------------------------------------------------------------------
-// Scan through the valid address range for a kernel binary.
-// This is uselessly slow in 64-bit environments so we don't even try it.
-// This scan is not enabled by default even for 32-bit targets.
-// Returns the address of the kernel if one was found, else
-// LLDB_INVALID_ADDRESS.
+// Scan through the valid address range for a kernel binary. This is uselessly
+// slow in 64-bit environments so we don't even try it. This scan is not
+// enabled by default even for 32-bit targets. Returns the address of the
+// kernel if one was found, else LLDB_INVALID_ADDRESS.
//----------------------------------------------------------------------
lldb::addr_t DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch(
Process *process) {
@@ -374,47 +366,30 @@ lldb::addr_t DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch(
}
//----------------------------------------------------------------------
-// Given an address in memory, look to see if there is a kernel image at that
-// address.
-// Returns a UUID; if a kernel was not found at that address, UUID.IsValid()
-// will be false.
+// Read the mach_header struct out of memory and return it.
+// Returns true if the mach_header was successfully read,
+// Returns false if there was a problem reading the header, or it was not
+// a Mach-O header.
//----------------------------------------------------------------------
-lldb_private::UUID
-DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
- Process *process) {
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
- if (addr == LLDB_INVALID_ADDRESS)
- return UUID();
-
- if (log)
- log->Printf("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: "
- "looking for kernel binary at 0x%" PRIx64,
- addr);
-
- // First try a quick test -- read the first 4 bytes and see if there is a
- // valid Mach-O magic field there
- // (the first field of the mach_header/mach_header_64 struct).
+bool
+DynamicLoaderDarwinKernel::ReadMachHeader(addr_t addr, Process *process, llvm::MachO::mach_header &header) {
Status read_error;
- uint8_t magicbuf[4];
- if (process->ReadMemoryFromInferior (addr, magicbuf, sizeof (magicbuf), read_error) != sizeof (magicbuf))
- return UUID();
+
+ // Read the mach header and see whether it looks like a kernel
+ if (process->DoReadMemory (addr, &header, sizeof(header), read_error) !=
+ sizeof(header))
+ return false;
const uint32_t magicks[] = { llvm::MachO::MH_MAGIC_64, llvm::MachO::MH_MAGIC, llvm::MachO::MH_CIGAM, llvm::MachO::MH_CIGAM_64};
bool found_matching_pattern = false;
for (size_t i = 0; i < llvm::array_lengthof (magicks); i++)
- if (::memcmp (magicbuf, &magicks[i], sizeof (magicbuf)) == 0)
+ if (::memcmp (&header.magic, &magicks[i], sizeof (uint32_t)) == 0)
found_matching_pattern = true;
if (found_matching_pattern == false)
- return UUID();
-
- // Read the mach header and see whether it looks like a kernel
- llvm::MachO::mach_header header;
- if (process->DoReadMemory(addr, &header, sizeof(header), read_error) !=
- sizeof(header))
- return UUID();
+ return false;
if (header.magic == llvm::MachO::MH_CIGAM ||
header.magic == llvm::MachO::MH_CIGAM_64) {
@@ -427,6 +402,35 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
header.flags = llvm::ByteSwap_32(header.flags);
}
+ return true;
+}
+
+//----------------------------------------------------------------------
+// Given an address in memory, look to see if there is a kernel image at that
+// address.
+// Returns a UUID; if a kernel was not found at that address, UUID.IsValid()
+// will be false.
+//----------------------------------------------------------------------
+lldb_private::UUID
+DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
+ Process *process) {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (addr == LLDB_INVALID_ADDRESS)
+ return UUID();
+
+ if (log)
+ log->Printf("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: "
+ "looking for kernel binary at 0x%" PRIx64,
+ addr);
+
+ llvm::MachO::mach_header header;
+
+ if (ReadMachHeader (addr, process, header) == false)
+ return UUID();
+
+ // First try a quick test -- read the first 4 bytes and see if there is a
+ // valid Mach-O magic field there
+ // (the first field of the mach_header/mach_header_64 struct).
// A kernel is an executable which does not have the dynamic link object flag
// set.
if (header.filetype == llvm::MachO::MH_EXECUTE &&
@@ -630,10 +634,8 @@ UUID DynamicLoaderDarwinKernel::KextImageInfo::GetUUID() const {
}
// Given the m_load_address from the kext summaries, and a UUID, try to create
-// an in-memory
-// Module at that address. Require that the MemoryModule have a matching UUID
-// and detect
-// if this MemoryModule is a kernel or a kext.
+// an in-memory Module at that address. Require that the MemoryModule have a
+// matching UUID and detect if this MemoryModule is a kernel or a kext.
//
// Returns true if m_memory_module_sp is now set to a valid Module.
@@ -646,10 +648,19 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule(
return false;
FileSpec file_spec;
- file_spec.SetFile(m_name.c_str(), false);
+ file_spec.SetFile(m_name.c_str(), false, FileSpec::Style::native);
+
+ llvm::MachO::mach_header mh;
+ size_t size_to_read = 512;
+ if (ReadMachHeader (m_load_address, process, mh)) {
+ if (mh.magic == llvm::MachO::MH_CIGAM || llvm::MachO::MH_MAGIC)
+ size_to_read = sizeof (llvm::MachO::mach_header) + mh.sizeofcmds;
+ if (mh.magic == llvm::MachO::MH_CIGAM_64 || llvm::MachO::MH_MAGIC_64)
+ size_to_read = sizeof (llvm::MachO::mach_header_64) + mh.sizeofcmds;
+ }
ModuleSP memory_module_sp =
- process->ReadModuleFromMemory(file_spec, m_load_address);
+ process->ReadModuleFromMemory(file_spec, m_load_address, size_to_read);
if (memory_module_sp.get() == NULL)
return false;
@@ -668,10 +679,8 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule(
}
// If this is a kext, and the kernel specified what UUID we should find at
- // this
- // load address, require that the memory module have a matching UUID or
- // something
- // has gone wrong and we should discard it.
+ // this load address, require that the memory module have a matching UUID or
+ // something has gone wrong and we should discard it.
if (m_uuid.IsValid()) {
if (m_uuid != memory_module_sp->GetUUID()) {
if (log) {
@@ -737,9 +746,8 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
Target &target = process->GetTarget();
- // If we don't have / can't create a memory module for this kext, don't try to
- // load it - we won't
- // have the correct segment load addresses.
+ // If we don't have / can't create a memory module for this kext, don't try
+ // to load it - we won't have the correct segment load addresses.
if (!ReadMemoryModule(process)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
@@ -772,9 +780,8 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
module_spec.GetUUID() = m_uuid;
module_spec.GetArchitecture() = target.GetArchitecture();
- // For the kernel, we really do need an on-disk file copy of the binary to
- // do anything useful.
- // This will force a clal to
+ // For the kernel, we really do need an on-disk file copy of the binary
+ // to do anything useful. This will force a clal to
if (IsKernel()) {
if (Symbols::DownloadObjectAndSymbolFile(module_spec, true)) {
if (module_spec.GetFileSpec().Exists()) {
@@ -791,10 +798,8 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
}
// If the current platform is PlatformDarwinKernel, create a ModuleSpec
- // with the filename set
- // to be the bundle ID for this kext, e.g.
- // "com.apple.filesystems.msdosfs", and ask the platform
- // to find it.
+ // with the filename set to be the bundle ID for this kext, e.g.
+ // "com.apple.filesystems.msdosfs", and ask the platform to find it.
PlatformSP platform_sp(target.GetPlatform());
if (!m_module_sp && platform_sp) {
ConstString platform_name(platform_sp->GetPluginName());
@@ -828,8 +833,9 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
}
}
- // If we managed to find a module, append it to the target's list of images.
- // If we also have a memory module, require that they have matching UUIDs
+ // If we managed to find a module, append it to the target's list of
+ // images. If we also have a memory module, require that they have matching
+ // UUIDs
if (m_module_sp) {
bool uuid_match_ok = true;
if (m_memory_module_sp) {
@@ -871,15 +877,15 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
SectionList *memory_section_list = memory_object_file->GetSectionList();
if (memory_section_list && ondisk_section_list) {
const uint32_t num_ondisk_sections = ondisk_section_list->GetSize();
- // There may be CTF sections in the memory image so we can't
- // always just compare the number of sections (which are actually
- // segments in mach-o parlance)
+ // There may be CTF sections in the memory image so we can't always
+ // just compare the number of sections (which are actually segments
+ // in mach-o parlance)
uint32_t sect_idx = 0;
- // Use the memory_module's addresses for each section to set the
- // file module's load address as appropriate. We don't want to use
- // a single slide value for the entire kext - different segments may
- // be slid different amounts by the kext loader.
+ // Use the memory_module's addresses for each section to set the file
+ // module's load address as appropriate. We don't want to use a
+ // single slide value for the entire kext - different segments may be
+ // slid different amounts by the kext loader.
uint32_t num_sections_loaded = 0;
for (sect_idx = 0; sect_idx < num_ondisk_sections; ++sect_idx) {
@@ -969,10 +975,9 @@ DynamicLoaderDarwinKernel::KextImageInfo::GetArchitecture() const {
}
//----------------------------------------------------------------------
-// Load the kernel module and initialize the "m_kernel" member. Return
-// true _only_ if the kernel is loaded the first time through (subsequent
-// calls to this function should return false after the kernel has been
-// already loaded).
+// Load the kernel module and initialize the "m_kernel" member. Return true
+// _only_ if the kernel is loaded the first time through (subsequent calls to
+// this function should return false after the kernel has been already loaded).
//----------------------------------------------------------------------
void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
if (!m_kext_summary_header_ptr_addr.IsValid()) {
@@ -996,9 +1001,8 @@ void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
m_kernel.SetLoadAddress(m_kernel_load_address);
if (m_kernel.GetLoadAddress() == LLDB_INVALID_ADDRESS &&
m_kernel.GetModule()) {
- // We didn't get a hint from the process, so we will
- // try the kernel at the address that it exists at in
- // the file if we have one
+ // We didn't get a hint from the process, so we will try the kernel at
+ // the address that it exists at in the file if we have one
ObjectFile *kernel_object_file = m_kernel.GetModule()->GetObjectFile();
if (kernel_object_file) {
addr_t load_address =
@@ -1011,8 +1015,7 @@ void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
if (load_address != file_address) {
// Don't accidentally relocate the kernel to the File address --
// the Load address has already been set to its actual in-memory
- // address.
- // Mark it as IsLoaded.
+ // address. Mark it as IsLoaded.
m_kernel.SetProcessStopId(m_process->GetStopID());
}
} else {
@@ -1028,10 +1031,10 @@ void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
}
}
- // The operating system plugin gets loaded and initialized in
- // LoadImageUsingMemoryModule when we discover the kernel dSYM. For a
- // core file in particular, that's the wrong place to do this, since
- // we haven't fixed up the section addresses yet. So let's redo it here.
+ // The operating system plugin gets loaded and initialized in
+ // LoadImageUsingMemoryModule when we discover the kernel dSYM. For a core
+ // file in particular, that's the wrong place to do this, since we haven't
+ // fixed up the section addresses yet. So let's redo it here.
LoadOperatingSystemPlugin(false);
if (m_kernel.IsLoaded() && m_kernel.GetModule()) {
@@ -1052,9 +1055,9 @@ void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
//----------------------------------------------------------------------
// Static callback function that gets called when our DYLD notification
-// breakpoint gets hit. We update all of our image infos and then
-// let our super class DynamicLoader class decide if we should stop
-// or not (based on global preference).
+// breakpoint gets hit. We update all of our image infos and then let our super
+// class DynamicLoader class decide if we should stop or not (based on global
+// preference).
//----------------------------------------------------------------------
bool DynamicLoaderDarwinKernel::BreakpointHitCallback(
void *baton, StoppointCallbackContext *context, user_id_t break_id,
@@ -1087,8 +1090,8 @@ bool DynamicLoaderDarwinKernel::ReadKextSummaryHeader() {
const uint32_t addr_size = m_kernel.GetAddressByteSize();
const ByteOrder byte_order = m_kernel.GetByteOrder();
Status error;
- // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure
- // which is currently 4 uint32_t and a pointer.
+ // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure which
+ // is currently 4 uint32_t and a pointer.
uint8_t buf[24];
DataExtractor data(buf, sizeof(buf), byte_order, addr_size);
const size_t count = 4 * sizeof(uint32_t) + addr_size;
@@ -1130,7 +1133,8 @@ bool DynamicLoaderDarwinKernel::ReadKextSummaryHeader() {
return false;
}
} else {
- // Versions less than 2 didn't have an entry size, it was hard coded
+ // Versions less than 2 didn't have an entry size, it was hard
+ // coded
m_kext_summary_header.entry_size =
KERNEL_MODULE_ENTRY_SIZE_VERSION_1;
}
@@ -1156,13 +1160,10 @@ bool DynamicLoaderDarwinKernel::ReadKextSummaryHeader() {
}
// We've either (a) just attached to a new kernel, or (b) the kexts-changed
-// breakpoint was hit
-// and we need to figure out what kexts have been added or removed.
-// Read the kext summaries from the inferior kernel memory, compare them against
-// the
-// m_known_kexts vector and update the m_known_kexts vector as needed to keep in
-// sync with the
-// inferior.
+// breakpoint was hit and we need to figure out what kexts have been added or
+// removed. Read the kext summaries from the inferior kernel memory, compare
+// them against the m_known_kexts vector and update the m_known_kexts vector as
+// needed to keep in sync with the inferior.
bool DynamicLoaderDarwinKernel::ParseKextSummaries(
const Address &kext_summary_addr, uint32_t count) {
@@ -1178,14 +1179,13 @@ bool DynamicLoaderDarwinKernel::ParseKextSummaries(
return false;
// read the plugin.dynamic-loader.darwin-kernel.load-kexts setting -- if the
- // user requested no
- // kext loading, don't print any messages about kexts & don't try to read
- // them.
+ // user requested no kext loading, don't print any messages about kexts &
+ // don't try to read them.
const bool load_kexts = GetGlobalProperties()->GetLoadKexts();
// By default, all kexts we've loaded in the past are marked as "remove" and
- // all of the kexts
- // we just found out about from ReadKextSummaries are marked as "add".
+ // all of the kexts we just found out about from ReadKextSummaries are marked
+ // as "add".
std::vector<bool> to_be_removed(m_known_kexts.size(), true);
std::vector<bool> to_be_added(count, true);
@@ -1195,8 +1195,8 @@ bool DynamicLoaderDarwinKernel::ParseKextSummaries(
const uint32_t new_kexts_size = kext_summaries.size();
const uint32_t old_kexts_size = m_known_kexts.size();
- // The m_known_kexts vector may have entries that have been Cleared,
- // or are a kernel.
+ // The m_known_kexts vector may have entries that have been Cleared, or are a
+ // kernel.
for (uint32_t old_kext = 0; old_kext < old_kexts_size; old_kext++) {
bool ignore = false;
KextImageInfo &image_info = m_known_kexts[old_kext];
@@ -1229,10 +1229,9 @@ bool DynamicLoaderDarwinKernel::ParseKextSummaries(
break;
}
}
- // If this "kext" entry is actually an alias for the kernel --
- // the kext was compiled into the kernel or something -- then
- // we don't want to load the kernel's text section at a different
- // address. Ignore this kext entry.
+ // If this "kext" entry is actually an alias for the kernel -- the kext was
+ // compiled into the kernel or something -- then we don't want to load the
+ // kernel's text section at a different address. Ignore this kext entry.
if (kext_summaries[new_kext].GetUUID().IsValid()
&& m_kernel.GetUUID().IsValid()
&& kext_summaries[new_kext].GetUUID() == m_kernel.GetUUID()) {
@@ -1322,9 +1321,8 @@ bool DynamicLoaderDarwinKernel::ParseKextSummaries(
s->Printf(".");
image_info.Clear();
// should pull it out of the KextImageInfos vector but that would
- // mutate the list and invalidate
- // the to_be_removed bool vector; leaving it in place once Cleared()
- // is relatively harmless.
+ // mutate the list and invalidate the to_be_removed bool vector;
+ // leaving it in place once Cleared() is relatively harmless.
}
}
m_process->GetTarget().ModulesDidUnload(unloaded_module_list, false);
@@ -1370,7 +1368,7 @@ uint32_t DynamicLoaderDarwinKernel::ReadKextSummaries(
if (name_data == NULL)
break;
image_infos[i].SetName((const char *)name_data);
- UUID uuid(extractor.GetData(&offset, 16), 16);
+ UUID uuid = UUID::fromOptionalData(extractor.GetData(&offset, 16), 16);
image_infos[i].SetUUID(uuid);
image_infos[i].SetLoadAddress(extractor.GetU64(&offset));
image_infos[i].SetSize(extractor.GetU64(&offset));
@@ -1405,36 +1403,18 @@ bool DynamicLoaderDarwinKernel::ReadAllKextSummaries() {
// Dump an image info structure to the file handle provided.
//----------------------------------------------------------------------
void DynamicLoaderDarwinKernel::KextImageInfo::PutToLog(Log *log) const {
- if (log == NULL)
- return;
- const uint8_t *u = static_cast<const uint8_t *>(m_uuid.GetBytes());
-
if (m_load_address == LLDB_INVALID_ADDRESS) {
- if (u) {
- log->Printf("\tuuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2."
- "2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\" (UNLOADED)",
- u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8], u[9],
- u[10], u[11], u[12], u[13], u[14], u[15], m_name.c_str());
- } else
- log->Printf("\tname=\"%s\" (UNLOADED)", m_name.c_str());
+ LLDB_LOG(log, "uuid={0} name=\"{1}\" (UNLOADED)", m_uuid.GetAsString(),
+ m_name);
} else {
- if (u) {
- log->Printf("\taddr=0x%16.16" PRIx64 " size=0x%16.16" PRIx64
- " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-"
- "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name=\"%s\"",
- m_load_address, m_size, u[0], u[1], u[2], u[3], u[4], u[5],
- u[6], u[7], u[8], u[9], u[10], u[11], u[12], u[13], u[14],
- u[15], m_name.c_str());
- } else {
- log->Printf("\t[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") name=\"%s\"",
- m_load_address, m_load_address + m_size, m_name.c_str());
- }
+ LLDB_LOG(log, "addr={0:x+16} size={1:x+16} uuid={2} name=\"{3}\"",
+ m_load_address, m_size, m_uuid.GetAsString(), m_name);
}
}
//----------------------------------------------------------------------
-// Dump the _dyld_all_image_infos members and all current image infos
-// that we have parsed to the file handle provided.
+// Dump the _dyld_all_image_infos members and all current image infos that we
+// have parsed to the file handle provided.
//----------------------------------------------------------------------
void DynamicLoaderDarwinKernel::PutToLog(Log *log) const {
if (log == NULL)
diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
index ad4f7c631d84..75998f1cc3be 100644
--- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
+++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
@@ -17,6 +17,9 @@
#include <vector>
// Other libraries and framework includes
+
+#include "lldb/Utility/SafeMachO.h"
+
// Project includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
@@ -284,6 +287,9 @@ protected:
static lldb::addr_t
SearchForKernelViaExhaustiveSearch(lldb_private::Process *process);
+ static bool
+ ReadMachHeader(lldb::addr_t addr, lldb_private::Process *process, llvm::MachO::mach_header &mh);
+
static lldb_private::UUID
CheckForKernelImageAtAddress(lldb::addr_t addr,
lldb_private::Process *process);
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index d0d60017e869..5ca20229d018 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -127,8 +127,8 @@ void DynamicLoaderHexagonDYLD::DidAttach() {
executable = GetTargetExecutable();
- // Find the difference between the desired load address in the elf file
- // and the real load address in memory
+ // Find the difference between the desired load address in the elf file and
+ // the real load address in memory
load_offset = ComputeLoadOffset();
// Check that there is a valid executable
@@ -157,10 +157,10 @@ void DynamicLoaderHexagonDYLD::DidAttach() {
// Callback for the target to give it the loaded module list
m_process->GetTarget().ModulesDidLoad(module_list);
- // Try to set a breakpoint at the rendezvous breakpoint.
- // DidLaunch uses ProbeEntry() instead. That sets a breakpoint,
- // at the dyld breakpoint address, with a callback so that when hit,
- // the dyld structure can be parsed.
+ // Try to set a breakpoint at the rendezvous breakpoint. DidLaunch uses
+ // ProbeEntry() instead. That sets a breakpoint, at the dyld breakpoint
+ // address, with a callback so that when hit, the dyld structure can be
+ // parsed.
if (!SetRendezvousBreakpoint()) {
// fail
}
@@ -203,8 +203,8 @@ ModuleSP DynamicLoaderHexagonDYLD::GetTargetExecutable() {
// TODO: What case is this code used?
executable = target.GetSharedModule(module_spec);
if (executable.get() != target.GetExecutableModulePointer()) {
- // Don't load dependent images since we are in dyld where we will know
- // and find out about all images that are loaded
+ // Don't load dependent images since we are in dyld where we will know and
+ // find out about all images that are loaded
const bool get_dependent_images = false;
target.SetExecutableModule(executable, get_dependent_images);
}
@@ -270,9 +270,8 @@ bool DynamicLoaderHexagonDYLD::SetRendezvousBreakpoint() {
// This is the original code, which want to look in the rendezvous structure
// to find the breakpoint address. Its backwards for us, since we can easily
- // find the breakpoint address, since it is exported in our executable.
- // We however know that we cant read the Rendezvous structure until we have
- // hit
+ // find the breakpoint address, since it is exported in our executable. We
+ // however know that we cant read the Rendezvous structure until we have hit
// the breakpoint once.
const ConstString dyldBpName("_rtld_debug_state");
addr_t break_addr = findSymbolAddress(m_process, dyldBpName);
@@ -326,8 +325,8 @@ bool DynamicLoaderHexagonDYLD::RendezvousBreakpointHit(
DynamicLoaderHexagonDYLD *dyld_instance = nullptr;
dyld_instance = static_cast<DynamicLoaderHexagonDYLD *>(baton);
- // if the dyld_instance is still not valid then
- // try to locate it on the symbol table
+ // if the dyld_instance is still not valid then try to locate it on the
+ // symbol table
if (!dyld_instance->m_rendezvous.IsValid()) {
Process *proc = dyld_instance->m_process;
@@ -480,8 +479,8 @@ void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() {
return;
}
- // The rendezvous class doesn't enumerate the main module, so track
- // that ourselves here.
+ // The rendezvous class doesn't enumerate the main module, so track that
+ // ourselves here.
ModuleSP executable = GetTargetExecutable();
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
@@ -517,12 +516,11 @@ addr_t DynamicLoaderHexagonDYLD::ComputeLoadOffset() {
return 0;
}
-// Here we must try to read the entry point directly from
-// the elf header. This is possible if the process is not
-// relocatable or dynamically linked.
+// Here we must try to read the entry point directly from the elf header. This
+// is possible if the process is not relocatable or dynamically linked.
//
-// an alternative is to look at the PC if we can be sure
-// that we have connected when the process is at the entry point.
+// an alternative is to look at the PC if we can be sure that we have connected
+// when the process is at the entry point.
// I dont think that is reliable for us.
addr_t DynamicLoaderHexagonDYLD::GetEntryPoint() {
if (m_entry_point != LLDB_INVALID_ADDRESS)
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
index c49cdc2f11b1..d5f60e07bd77 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp
@@ -115,8 +115,8 @@ bool HexagonDYLDRendezvous::UpdateSOEntries() {
if (m_current.map_addr == 0)
return false;
- // When the previous and current states are consistent this is the first
- // time we have been asked to update. Just take a snapshot of the currently
+ // When the previous and current states are consistent this is the first time
+ // we have been asked to update. Just take a snapshot of the currently
// loaded modules.
if (m_previous.state == eConsistent && m_current.state == eConsistent)
return TakeSnapshot(m_soentries);
@@ -126,8 +126,8 @@ bool HexagonDYLDRendezvous::UpdateSOEntries() {
if (m_current.state == eAdd || m_current.state == eDelete) {
// this is a fudge so that we can clear the assert below.
m_previous.state = eConsistent;
- // We hit this assert on the 2nd run of this function after running the calc
- // example
+ // We hit this assert on the 2nd run of this function after running the
+ // calc example
assert(m_previous.state == eConsistent);
m_soentries.clear();
m_added_soentries.clear();
@@ -159,9 +159,9 @@ bool HexagonDYLDRendezvous::UpdateSOEntriesForAddition() {
if (!ReadSOEntryFromMemory(cursor, entry))
return false;
- // Only add shared libraries and not the executable.
- // On Linux this is indicated by an empty path in the entry.
- // On FreeBSD it is the name of the executable.
+ // Only add shared libraries and not the executable. On Linux this is
+ // indicated by an empty path in the entry. On FreeBSD it is the name of
+ // the executable.
if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
continue;
@@ -204,9 +204,9 @@ bool HexagonDYLDRendezvous::TakeSnapshot(SOEntryList &entry_list) {
if (!ReadSOEntryFromMemory(cursor, entry))
return false;
- // Only add shared libraries and not the executable.
- // On Linux this is indicated by an empty path in the entry.
- // On FreeBSD it is the name of the executable.
+ // Only add shared libraries and not the executable. On Linux this is
+ // indicated by an empty path in the entry. On FreeBSD it is the name of
+ // the executable.
if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
continue;
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
index b68f89b9ce83..bdf6bae75197 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
@@ -11,8 +11,10 @@
#define liblldb_HexagonDYLDRendezvous_H_
// C Includes
+#include <limits.h> // for PATH_MAX
// C++ Includes
#include <list>
+#include <map>
#include <string>
// Other libraries and framework includes
@@ -24,12 +26,12 @@ class Process;
}
/// @class HexagonDYLDRendezvous
-/// @brief Interface to the runtime linker.
+/// Interface to the runtime linker.
///
/// A structure is present in a processes memory space which is updated by the
-/// runtime liker each time a module is loaded or unloaded. This class provides
-/// an interface to this structure and maintains a consistent snapshot of the
-/// currently loaded modules.
+/// runtime liker each time a module is loaded or unloaded. This class
+/// provides an interface to this structure and maintains a consistent
+/// snapshot of the currently loaded modules.
class HexagonDYLDRendezvous {
// This structure is used to hold the contents of the debug rendezvous
@@ -124,7 +126,7 @@ public:
void DumpToLog(lldb_private::Log *log) const;
- /// @brief Constants describing the state of the rendezvous.
+ /// Constants describing the state of the rendezvous.
///
/// @see GetState().
enum RendezvousState {
@@ -133,8 +135,8 @@ public:
eDelete,
};
- /// @brief Structure representing the shared objects currently loaded into
- /// the inferior process.
+ /// Structure representing the shared objects currently loaded into the
+ /// inferior process.
///
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
@@ -198,7 +200,8 @@ protected:
/// List of SOEntry objects corresponding to the current link map state.
SOEntryList m_soentries;
- /// List of SOEntry's added to the link map since the last call to Resolve().
+ /// List of SOEntry's added to the link map since the last call to
+ /// Resolve().
SOEntryList m_added_soentries;
/// List of SOEntry's removed from the link map since the last call to
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index 703b461f6fe1..c6439a30c8a3 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -112,8 +112,8 @@ ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo(
if (module_sp && !module_spec.GetUUID().IsValid() &&
!module_sp->GetUUID().IsValid()) {
- // No UUID, we must rely upon the cached module modification
- // time and the modification time of the file on disk
+ // No UUID, we must rely upon the cached module modification time and the
+ // modification time of the file on disk
if (module_sp->GetModificationTime() !=
FileSystem::GetModificationTime(module_sp->GetFileSpec()))
module_sp.reset();
@@ -198,8 +198,7 @@ void DynamicLoaderDarwin::UnloadAllImages() {
ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
// Don't remove dyld - else we'll lose our breakpoint notifying us about
- // libraries
- // being re-loaded...
+ // libraries being re-loaded...
if (module_sp.get() != nullptr && module_sp.get() != dyld_sp.get()) {
UnloadSections(module_sp);
unloaded_modules_list.Append(module_sp);
@@ -219,8 +218,8 @@ void DynamicLoaderDarwin::UnloadAllImages() {
}
//----------------------------------------------------------------------
-// Update the load addresses for all segments in MODULE using the
-// updated INFO that is passed in.
+// Update the load addresses for all segments in MODULE using the updated INFO
+// that is passed in.
//----------------------------------------------------------------------
bool DynamicLoaderDarwin::UpdateImageLoadAddress(Module *module,
ImageInfo &info) {
@@ -231,13 +230,12 @@ bool DynamicLoaderDarwin::UpdateImageLoadAddress(Module *module,
SectionList *section_list = image_object_file->GetSectionList();
if (section_list) {
std::vector<uint32_t> inaccessible_segment_indexes;
- // We now know the slide amount, so go through all sections
- // and update the load addresses with the correct values.
+ // We now know the slide amount, so go through all sections and update
+ // the load addresses with the correct values.
const size_t num_segments = info.segments.size();
for (size_t i = 0; i < num_segments; ++i) {
- // Only load a segment if it has protections. Things like
- // __PAGEZERO don't have any protections, and they shouldn't
- // be slid
+ // Only load a segment if it has protections. Things like __PAGEZERO
+ // don't have any protections, and they shouldn't be slid
SectionSP section_sp(
section_list->FindSectionByName(info.segments[i].name));
@@ -249,10 +247,10 @@ bool DynamicLoaderDarwin::UpdateImageLoadAddress(Module *module,
static ConstString g_section_name_LINKEDIT("__LINKEDIT");
if (section_sp) {
- // __LINKEDIT sections from files in the shared cache
- // can overlap so check to see what the segment name is
- // and pass "false" so we don't warn of overlapping
- // "Section" objects, and "true" for all other sections.
+ // __LINKEDIT sections from files in the shared cache can overlap
+ // so check to see what the segment name is and pass "false" so
+ // we don't warn of overlapping "Section" objects, and "true" for
+ // all other sections.
const bool warn_multiple =
section_sp->GetName() != g_section_name_LINKEDIT;
@@ -270,13 +268,12 @@ bool DynamicLoaderDarwin::UpdateImageLoadAddress(Module *module,
}
}
- // If the loaded the file (it changed) and we have segments that
- // are not readable or writeable, add them to the invalid memory
- // region cache for the process. This will typically only be
- // the __PAGEZERO segment in the main executable. We might be able
- // to apply this more generally to more sections that have no
- // protections in the future, but for now we are going to just
- // do __PAGEZERO.
+ // If the loaded the file (it changed) and we have segments that are
+ // not readable or writeable, add them to the invalid memory region
+ // cache for the process. This will typically only be the __PAGEZERO
+ // segment in the main executable. We might be able to apply this more
+ // generally to more sections that have no protections in the future,
+ // but for now we are going to just do __PAGEZERO.
if (changed && !inaccessible_segment_indexes.empty()) {
for (uint32_t i = 0; i < inaccessible_segment_indexes.size(); ++i) {
const uint32_t seg_idx = inaccessible_segment_indexes[i];
@@ -344,8 +341,7 @@ bool DynamicLoaderDarwin::UnloadModuleSections(Module *module,
}
// Given a JSON dictionary (from debugserver, most likely) of binary images
-// loaded in the inferior
-// process, add the images to the ImageInfo collection.
+// loaded in the inferior process, add the images to the ImageInfo collection.
bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
StructuredData::ObjectSP image_details,
@@ -378,7 +374,8 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
image_infos[i].mod_date =
image->GetValueForKey("mod_date")->GetAsInteger()->GetValue();
image_infos[i].file_spec.SetFile(
- image->GetValueForKey("pathname")->GetAsString()->GetValue(), false);
+ image->GetValueForKey("pathname")->GetAsString()->GetValue(), false,
+ FileSpec::Style::native);
StructuredData::Dictionary *mh =
image->GetValueForKey("mach_header")->GetAsDictionary();
@@ -412,8 +409,7 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
}
// Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
- // currently send them
- // in the reply.
+ // currently send them in the reply.
if (mh->HasKey("flags"))
image_infos[i].header.flags =
@@ -454,8 +450,7 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue();
// Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't
- // currently send them
- // in the reply.
+ // currently send them in the reply.
if (seg->HasKey("initprot"))
segment.initprot =
@@ -481,25 +476,23 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
image_infos[i].uuid.SetFromStringRef(
image->GetValueForKey("uuid")->GetAsString()->GetValue());
- // All sections listed in the dyld image info structure will all
- // either be fixed up already, or they will all be off by a single
- // slide amount that is determined by finding the first segment
- // that is at file offset zero which also has bytes (a file size
- // that is greater than zero) in the object file.
+ // All sections listed in the dyld image info structure will all either be
+ // fixed up already, or they will all be off by a single slide amount that
+ // is determined by finding the first segment that is at file offset zero
+ // which also has bytes (a file size that is greater than zero) in the
+ // object file.
// Determine the slide amount (if any)
const size_t num_sections = image_infos[i].segments.size();
for (size_t k = 0; k < num_sections; ++k) {
- // Iterate through the object file sections to find the
- // first section that starts of file offset zero and that
- // has bytes in the file...
+ // Iterate through the object file sections to find the first section
+ // that starts of file offset zero and that has bytes in the file...
if ((image_infos[i].segments[k].fileoff == 0 &&
image_infos[i].segments[k].filesize > 0) ||
(image_infos[i].segments[k].name == ConstString("__TEXT"))) {
image_infos[i].slide =
image_infos[i].address - image_infos[i].segments[k].vmaddr;
- // We have found the slide amount, so we can exit
- // this for loop.
+ // We have found the slide amount, so we can exit this for loop.
break;
}
}
@@ -520,16 +513,15 @@ void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos(
const size_t image_infos_size = image_infos.size();
for (size_t i = 0; i < image_infos_size; i++) {
if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER) {
- // In a "simulator" process (an x86 process that is ios/tvos/watchos)
- // we will have two dyld modules -- a "dyld" that we want to keep track
- // of,
- // and a "dyld_sim" which we don't need to keep track of here.
- // If the target is an x86 system and the OS of the dyld binary is
+ // In a "simulator" process (an x86 process that is ios/tvos/watchos) we
+ // will have two dyld modules -- a "dyld" that we want to keep track of,
+ // and a "dyld_sim" which we don't need to keep track of here. If the
+ // target is an x86 system and the OS of the dyld binary is
// ios/tvos/watchos, then we are looking at dyld_sym.
- // debugserver has only recently (late 2016) started sending up the
- // os type for each binary it sees -- so if we don't have an os
- // type, use a filename check as our next best guess.
+ // debugserver has only recently (late 2016) started sending up the os
+ // type for each binary it sees -- so if we don't have an os type, use a
+ // filename check as our next best guess.
if (image_infos[i].os_type == llvm::Triple::OSType::UnknownOS) {
if (image_infos[i].file_spec.GetFilename() != g_dyld_sim_filename) {
dyld_idx = i;
@@ -543,7 +535,8 @@ void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos(
}
}
else {
- // catch-all for any other environment -- trust that dyld is actually dyld
+ // catch-all for any other environment -- trust that dyld is actually
+ // dyld
dyld_idx = i;
}
} else if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) {
@@ -669,11 +662,10 @@ bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
}
}
- // UpdateImageLoadAddress will return true if any segments
- // change load address. We need to check this so we don't
- // mention that all loaded shared libraries are newly loaded
- // each time we hit out dyld breakpoint since dyld will list all
- // shared libraries each time.
+ // UpdateImageLoadAddress will return true if any segments change load
+ // address. We need to check this so we don't mention that all loaded
+ // shared libraries are newly loaded each time we hit out dyld breakpoint
+ // since dyld will list all shared libraries each time.
if (UpdateImageLoadAddress(image_module_sp.get(), image_infos[idx])) {
target_images.AppendIfNeeded(image_module_sp);
loaded_module_list.AppendIfNeeded(image_module_sp);
@@ -692,12 +684,11 @@ bool DynamicLoaderDarwin::AddModulesUsingImageInfos(
//----------------------------------------------------------------------
// On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch
-// functions written in hand-written assembly, and also have hand-written unwind
-// information in the eh_frame section. Normally we prefer analyzing the
-// assembly instructions of a currently executing frame to unwind from that
-// frame --
-// but on hand-written functions this profiling can fail. We should use the
-// eh_frame instructions for these functions all the time.
+// functions written in hand-written assembly, and also have hand-written
+// unwind information in the eh_frame section. Normally we prefer analyzing
+// the assembly instructions of a currently executing frame to unwind from that
+// frame -- but on hand-written functions this profiling can fail. We should
+// use the eh_frame instructions for these functions all the time.
//
// As an aside, it would be better if the eh_frame entries had a flag (or were
// extensible so they could have an Apple-specific flag) which indicates that
@@ -756,35 +747,14 @@ DynamicLoaderDarwin::ImageInfo::FindSegment(const ConstString &name) const {
// Dump an image info structure to the file handle provided.
//----------------------------------------------------------------------
void DynamicLoaderDarwin::ImageInfo::PutToLog(Log *log) const {
- if (log == NULL)
+ if (!log)
return;
- const uint8_t *u = (const uint8_t *)uuid.GetBytes();
-
if (address == LLDB_INVALID_ADDRESS) {
- if (u) {
- log->Printf("\t modtime=0x%8.8" PRIx64
- " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-"
- "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s' (UNLOADED)",
- mod_date, u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7],
- u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15],
- file_spec.GetPath().c_str());
- } else
- log->Printf("\t modtime=0x%8.8" PRIx64
- " path='%s' (UNLOADED)",
- mod_date, file_spec.GetPath().c_str());
+ LLDB_LOG(log, "modtime={0:x+8} uuid={1} path='{2}' (UNLOADED)", mod_date,
+ uuid.GetAsString(), file_spec.GetPath());
} else {
- if (u) {
- log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64
- " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-"
- "%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s'",
- address, mod_date, u[0], u[1], u[2], u[3], u[4], u[5], u[6],
- u[7], u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15],
- file_spec.GetPath().c_str());
- } else {
- log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64
- " path='%s'",
- address, mod_date, file_spec.GetPath().c_str());
- }
+ LLDB_LOG(log, "address={0:x+16} modtime={1:x+8} uuid={2} path='{3}'",
+ address, mod_date, uuid.GetAsString(), file_spec.GetPath());
for (uint32_t i = 0; i < segments.size(); ++i)
segments[i].PutToLog(log, slide);
}
@@ -817,8 +787,8 @@ void DynamicLoaderDarwin::PrivateProcessStateChanged(Process *process,
break;
case eStateStopped:
- // Keep trying find dyld and set our notification breakpoint each time
- // we stop until we succeed
+ // Keep trying find dyld and set our notification breakpoint each time we
+ // stop until we succeed
if (!DidSetNotificationBreakpoint() && m_process->IsAlive()) {
if (NeedToDoInitialImageFetch())
DoInitialImageFetch();
@@ -956,8 +926,8 @@ DynamicLoaderDarwin::GetStepThroughTrampolinePlan(Thread &thread,
}
if (addresses.size() > 0) {
- // First check whether any of the addresses point to Indirect symbols, and
- // if they do, resolve them:
+ // First check whether any of the addresses point to Indirect symbols,
+ // and if they do, resolve them:
std::vector<lldb::addr_t> load_addrs;
for (Address address : addresses) {
Symbol *symbol = address.CalculateSymbolContextSymbol();
@@ -1073,10 +1043,10 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,
const lldb::addr_t pthread_key = data.GetAddress(&offset);
const lldb::addr_t tls_offset = data.GetAddress(&offset);
if (pthread_key != 0) {
- // First check to see if we have already figured out the location
- // of TLS data for the pthread_key on a specific thread yet. If we
- // have we can re-use it since its location will not change unless
- // the process execs.
+ // First check to see if we have already figured out the location of
+ // TLS data for the pthread_key on a specific thread yet. If we have we
+ // can re-use it since its location will not change unless the process
+ // execs.
const tid_t tid = thread_sp->GetID();
auto tid_pos = m_tid_to_tls_map.find(tid);
if (tid_pos != m_tid_to_tls_map.end()) {
@@ -1131,34 +1101,29 @@ DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp,
bool DynamicLoaderDarwin::UseDYLDSPI(Process *process) {
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
- uint32_t major, minor, update;
-
bool use_new_spi_interface = false;
- if (process->GetHostOSVersion(major, minor, update)) {
+ llvm::VersionTuple version = process->GetHostOSVersion();
+ if (!version.empty()) {
const llvm::Triple::OSType os_type =
process->GetTarget().GetArchitecture().GetTriple().getOS();
// macOS 10.12 and newer
if (os_type == llvm::Triple::MacOSX &&
- (major > 10 || (major == 10 && minor >= 12))) {
+ version >= llvm::VersionTuple(10, 12))
use_new_spi_interface = true;
- }
// iOS 10 and newer
- if (os_type == llvm::Triple::IOS && major >= 10) {
+ if (os_type == llvm::Triple::IOS && version >= llvm::VersionTuple(10))
use_new_spi_interface = true;
- }
// tvOS 10 and newer
- if (os_type == llvm::Triple::TvOS && major >= 10) {
+ if (os_type == llvm::Triple::TvOS && version >= llvm::VersionTuple(10))
use_new_spi_interface = true;
- }
// watchOS 3 and newer
- if (os_type == llvm::Triple::WatchOS && major >= 3) {
+ if (os_type == llvm::Triple::WatchOS && version >= llvm::VersionTuple(3))
use_new_spi_interface = true;
- }
}
if (log) {
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
index 66085a23759b..4a8ad38d1785 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
@@ -29,9 +29,9 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// Create an instance of this class. This function is filled into
-// the plugin info class that gets handed out by the plugin factory and
-// allows the lldb to instantiate an instance of this class.
+// Create an instance of this class. This function is filled into the plugin
+// info class that gets handed out by the plugin factory and allows the lldb to
+// instantiate an instance of this class.
//----------------------------------------------------------------------
DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process,
bool force) {
@@ -144,17 +144,18 @@ void DynamicLoaderMacOS::ClearNotificationBreakpoint() {
}
//----------------------------------------------------------------------
-// Try and figure out where dyld is by first asking the Process
-// if it knows (which currently calls down in the lldb::Process
-// to get the DYLD info (available on SnowLeopard only). If that fails,
-// then check in the default addresses.
+// Try and figure out where dyld is by first asking the Process if it knows
+// (which currently calls down in the lldb::Process to get the DYLD info
+// (available on SnowLeopard only). If that fails, then check in the default
+// addresses.
//----------------------------------------------------------------------
void DynamicLoaderMacOS::DoInitialImageFetch() {
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
- // Remove any binaries we pre-loaded in the Target before launching/attaching.
- // If the same binaries are present in the process, we'll get them from the
- // shared module cache, we won't need to re-load them from disk.
+ // Remove any binaries we pre-loaded in the Target before
+ // launching/attaching. If the same binaries are present in the process,
+ // we'll get them from the shared module cache, we won't need to re-load them
+ // from disk.
UnloadAllImages();
StructuredData::ObjectSP all_image_info_json_sp(
@@ -184,9 +185,9 @@ bool DynamicLoaderMacOS::NeedToDoInitialImageFetch() { return true; }
//----------------------------------------------------------------------
// Static callback function that gets called when our DYLD notification
-// breakpoint gets hit. We update all of our image infos and then
-// let our super class DynamicLoader class decide if we should stop
-// or not (based on global preference).
+// breakpoint gets hit. We update all of our image infos and then let our super
+// class DynamicLoader class decide if we should stop or not (based on global
+// preference).
//----------------------------------------------------------------------
bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
StoppointCallbackContext *context,
@@ -194,11 +195,10 @@ bool DynamicLoaderMacOS::NotifyBreakpointHit(void *baton,
lldb::user_id_t break_loc_id) {
// Let the event know that the images have changed
// DYLD passes three arguments to the notification breakpoint.
- // Arg1: enum dyld_notify_mode mode - 0 = adding, 1 = removing, 2 = remove all
- // Arg2: unsigned long icount - Number of shared libraries
- // added/removed
- // Arg3: uint64_t mach_headers[] - Array of load addresses of binaries
- // added/removed
+ // Arg1: enum dyld_notify_mode mode - 0 = adding, 1 = removing, 2 = remove
+ // all Arg2: unsigned long icount - Number of shared libraries
+ // added/removed Arg3: uint64_t mach_headers[] - Array of load addresses
+ // of binaries added/removed
DynamicLoaderMacOS *dyld_instance = (DynamicLoaderMacOS *)baton;
@@ -328,8 +328,8 @@ void DynamicLoaderMacOS::AddBinaries(
}
}
-// Dump the _dyld_all_image_infos members and all current image infos
-// that we have parsed to the file handle provided.
+// Dump the _dyld_all_image_infos members and all current image infos that we
+// have parsed to the file handle provided.
//----------------------------------------------------------------------
void DynamicLoaderMacOS::PutToLog(Log *log) const {
if (log == NULL)
@@ -432,9 +432,9 @@ Status DynamicLoaderMacOS::CanLoadImage() {
}
}
- // Default assumption is that it is OK to load images.
- // Only say that we cannot load images if we find the symbol in libdyld and it
- // indicates that we cannot.
+ // Default assumption is that it is OK to load images. Only say that we
+ // cannot load images if we find the symbol in libdyld and it indicates that
+ // we cannot.
if (symbol_address != LLDB_INVALID_ADDRESS) {
{
@@ -445,11 +445,11 @@ Status DynamicLoaderMacOS::CanLoadImage() {
}
}
} else {
- // If we were unable to find _dyld_global_lock_held in any modules, or it is
- // not loaded into memory yet, we may be at process startup (sitting
- // at _dyld_start) - so we should not allow dlopen calls.
- // But if we found more than one module then we are clearly past _dyld_start
- // so in that case we'll default to "it's safe".
+ // If we were unable to find _dyld_global_lock_held in any modules, or it
+ // is not loaded into memory yet, we may be at process startup (sitting at
+ // _dyld_start) - so we should not allow dlopen calls. But if we found more
+ // than one module then we are clearly past _dyld_start so in that case
+ // we'll default to "it's safe".
if (num_modules <= 1)
error.SetErrorString("could not find the dyld library or "
"the dyld lock symbol");
@@ -472,7 +472,9 @@ bool DynamicLoaderMacOS::GetSharedCacheInformation(
info_dict = info->GetAsDictionary();
}
- // {"shared_cache_base_address":140735683125248,"shared_cache_uuid":"DDB8D70C-C9A2-3561-B2C8-BE48A4F33F96","no_shared_cache":false,"shared_cache_private_cache":false}
+ // {"shared_cache_base_address":140735683125248,"shared_cache_uuid
+ // ":"DDB8D70C-
+ // C9A2-3561-B2C8-BE48A4F33F96","no_shared_cache":false,"shared_cache_private_cache":false}
if (info_dict && info_dict->HasKey("shared_cache_uuid") &&
info_dict->HasKey("no_shared_cache") &&
@@ -482,7 +484,7 @@ bool DynamicLoaderMacOS::GetSharedCacheInformation(
std::string uuid_str =
info_dict->GetValueForKey("shared_cache_uuid")->GetStringValue();
if (!uuid_str.empty())
- uuid.SetFromCString(uuid_str.c_str());
+ uuid.SetFromStringRef(uuid_str);
if (info_dict->GetValueForKey("no_shared_cache")->GetBooleanValue() ==
false)
using_shared_cache = eLazyBoolYes;
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index e0def58f41c1..265f19d0ca06 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -49,9 +49,9 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// Create an instance of this class. This function is filled into
-// the plugin info class that gets handed out by the plugin factory and
-// allows the lldb to instantiate an instance of this class.
+// Create an instance of this class. This function is filled into the plugin
+// info class that gets handed out by the plugin factory and allows the lldb to
+// instantiate an instance of this class.
//----------------------------------------------------------------------
DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process,
bool force) {
@@ -123,17 +123,18 @@ bool DynamicLoaderMacOSXDYLD::ProcessDidExec() {
const addr_t shlib_addr = m_process->GetImageInfoAddress();
if (m_process_image_addr_is_all_images_infos == true &&
shlib_addr != m_dyld_all_image_infos_addr) {
- // The image info address from the process is the 'dyld_all_image_infos'
- // address and it has changed.
+ // The image info address from the process is the
+ // 'dyld_all_image_infos' address and it has changed.
did_exec = true;
} else if (m_process_image_addr_is_all_images_infos == false &&
shlib_addr == m_dyld.address) {
- // The image info address from the process is the mach_header
- // address for dyld and it has changed.
+ // The image info address from the process is the mach_header address
+ // for dyld and it has changed.
did_exec = true;
} else {
// ASLR might be disabled and dyld could have ended up in the same
- // location. We should try and detect if we are stopped at '_dyld_start'
+ // location. We should try and detect if we are stopped at
+ // '_dyld_start'
ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
if (thread_sp) {
lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
@@ -185,16 +186,15 @@ void DynamicLoaderMacOSXDYLD::ClearNotificationBreakpoint() {
}
//----------------------------------------------------------------------
-// Try and figure out where dyld is by first asking the Process
-// if it knows (which currently calls down in the lldb::Process
-// to get the DYLD info (available on SnowLeopard only). If that fails,
-// then check in the default addresses.
+// Try and figure out where dyld is by first asking the Process if it knows
+// (which currently calls down in the lldb::Process to get the DYLD info
+// (available on SnowLeopard only). If that fails, then check in the default
+// addresses.
//----------------------------------------------------------------------
void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() {
if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) {
- // Check the image info addr as it might point to the
- // mach header for dyld, or it might point to the
- // dyld_all_image_infos struct
+ // Check the image info addr as it might point to the mach header for dyld,
+ // or it might point to the dyld_all_image_infos struct
const addr_t shlib_addr = m_process->GetImageInfoAddress();
if (shlib_addr != LLDB_INVALID_ADDRESS) {
ByteOrder byte_order =
@@ -255,8 +255,7 @@ void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() {
}
//----------------------------------------------------------------------
-// Assume that dyld is in memory at ADDR and try to parse it's load
-// commands
+// Assume that dyld is in memory at ADDR and try to parse it's load commands
//----------------------------------------------------------------------
bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(
lldb::addr_t addr) {
@@ -287,10 +286,10 @@ bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(
// Update all image infos
InitializeFromAllImageInfos();
- // If we didn't have an executable before, but now we do, then the
- // dyld module shared pointer might be unique and we may need to add
- // it again (since Target::SetExecutableModule() will clear the
- // images). So append the dyld module back to the list if it is
+ // If we didn't have an executable before, but now we do, then the dyld
+ // module shared pointer might be unique and we may need to add it again
+ // (since Target::SetExecutableModule() will clear the images). So append
+ // the dyld module back to the list if it is
/// unique!
if (dyld_module_sp) {
target.GetImages().AppendIfNeeded(dyld_module_sp);
@@ -315,18 +314,18 @@ bool DynamicLoaderMacOSXDYLD::NeedToDoInitialImageFetch() {
//----------------------------------------------------------------------
// Static callback function that gets called when our DYLD notification
-// breakpoint gets hit. We update all of our image infos and then
-// let our super class DynamicLoader class decide if we should stop
-// or not (based on global preference).
+// breakpoint gets hit. We update all of our image infos and then let our super
+// class DynamicLoader class decide if we should stop or not (based on global
+// preference).
//----------------------------------------------------------------------
bool DynamicLoaderMacOSXDYLD::NotifyBreakpointHit(
void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
lldb::user_id_t break_loc_id) {
// Let the event know that the images have changed
// DYLD passes three arguments to the notification breakpoint.
- // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing
- // Arg2: uint32_t infoCount - Number of shared libraries added
- // Arg3: dyld_image_info info[] - Array of structs of the form:
+ // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing Arg2: uint32_t
+ // infoCount - Number of shared libraries added Arg3: dyld_image_info
+ // info[] - Array of structs of the form:
// const struct mach_header
// *imageLoadAddress
// const char *imageFilePath
@@ -335,11 +334,10 @@ bool DynamicLoaderMacOSXDYLD::NotifyBreakpointHit(
DynamicLoaderMacOSXDYLD *dyld_instance = (DynamicLoaderMacOSXDYLD *)baton;
// First step is to see if we've already initialized the all image infos. If
- // we haven't then this function
- // will do so and return true. In the course of initializing the
- // all_image_infos it will read the complete
- // current state, so we don't need to figure out what has changed from the
- // data passed in to us.
+ // we haven't then this function will do so and return true. In the course
+ // of initializing the all_image_infos it will read the complete current
+ // state, so we don't need to figure out what has changed from the data
+ // passed in to us.
ExecutionContext exe_ctx(context->exe_ctx_ref);
Process *process = exe_ctx.GetProcessPtr();
@@ -388,11 +386,9 @@ bool DynamicLoaderMacOSXDYLD::NotifyBreakpointHit(
argument_values.GetValueAtIndex(1)->GetScalar().UInt(-1);
if (image_infos_count != static_cast<uint32_t>(-1)) {
// Got the number added, now go through the array of added elements,
- // putting out the mach header
- // address, and adding the image.
- // Note, I'm not putting in logging here, since the AddModules &
- // RemoveModules functions do
- // all the logging internally.
+ // putting out the mach header address, and adding the image. Note,
+ // I'm not putting in logging here, since the AddModules &
+ // RemoveModules functions do all the logging internally.
lldb::addr_t image_infos_addr =
argument_values.GetValueAtIndex(2)->GetScalar().ULongLong();
@@ -467,12 +463,12 @@ bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure() {
if (m_process->ReadMemory(m_dyld_all_image_infos_addr, buf, 4, error) ==
4) {
m_dyld_all_image_infos.version = data.GetU32(&offset);
- // If anything in the high byte is set, we probably got the byte
- // order incorrect (the process might not have it set correctly
- // yet due to attaching to a program without a specified file).
+ // If anything in the high byte is set, we probably got the byte order
+ // incorrect (the process might not have it set correctly yet due to
+ // attaching to a program without a specified file).
if (m_dyld_all_image_infos.version & 0xff000000) {
- // We have guessed the wrong byte order. Swap it and try
- // reading the version again.
+ // We have guessed the wrong byte order. Swap it and try reading the
+ // version again.
if (byte_order == eByteOrderLittle)
byte_order = eByteOrderBig;
else
@@ -508,21 +504,17 @@ bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure() {
uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset);
// When we started, we were given the actual address of the
- // all_image_infos
- // struct (probably via TASK_DYLD_INFO) in memory - this address is
- // stored in
- // m_dyld_all_image_infos_addr and is the most accurate address we have.
+ // all_image_infos struct (probably via TASK_DYLD_INFO) in memory -
+ // this address is stored in m_dyld_all_image_infos_addr and is the
+ // most accurate address we have.
// We read the dyld_all_image_infos struct from memory; it contains its
- // own address.
- // If the address in the struct does not match the actual address,
- // the dyld we're looking at has been loaded at a different location
- // (slid) from
- // where it intended to load. The addresses in the dyld_all_image_infos
- // struct
- // are the original, non-slid addresses, and need to be adjusted. Most
- // importantly
- // the address of dyld and the notification address need to be adjusted.
+ // own address. If the address in the struct does not match the actual
+ // address, the dyld we're looking at has been loaded at a different
+ // location (slid) from where it intended to load. The addresses in
+ // the dyld_all_image_infos struct are the original, non-slid
+ // addresses, and need to be adjusted. Most importantly the address of
+ // dyld and the notification address need to be adjusted.
if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) {
uint64_t image_infos_offset =
@@ -615,14 +607,13 @@ bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress(
image_infos[idx].PutToLog(log);
}
- // Remove this image_infos from the m_all_image_infos. We do the comparison
- // by address
- // rather than by file spec because we can have many modules with the same
- // "file spec" in the
- // case that they are modules loaded from memory.
+ // Remove this image_infos from the m_all_image_infos. We do the
+ // comparison by address rather than by file spec because we can have many
+ // modules with the same "file spec" in the case that they are modules
+ // loaded from memory.
//
- // Also copy over the uuid from the old entry to the removed entry so we can
- // use it to lookup the module in the module list.
+ // Also copy over the uuid from the old entry to the removed entry so we
+ // can use it to lookup the module in the module list.
ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end();
for (pos = m_dyld_image_infos.begin(); pos != end; pos++) {
@@ -630,8 +621,7 @@ bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress(
image_infos[idx].uuid = (*pos).uuid;
// Add the module from this image_info to the "unloaded_module_list".
- // We'll remove them all at
- // one go later on.
+ // We'll remove them all at one go later on.
ModuleSP unload_image_module_sp(
FindTargetModuleForImageInfo(image_infos[idx], false, NULL));
@@ -703,7 +693,8 @@ bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
// don't resolve the path
if (error.Success()) {
const bool resolve_path = false;
- image_infos[i].file_spec.SetFile(raw_path, resolve_path);
+ image_infos[i].file_spec.SetFile(raw_path, resolve_path,
+ FileSpec::Style::native);
}
}
return true;
@@ -713,11 +704,10 @@ bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
}
//----------------------------------------------------------------------
-// If we have found where the "_dyld_all_image_infos" lives in memory,
-// read the current info from it, and then update all image load
-// addresses (or lack thereof). Only do this if this is the first time
-// we're reading the dyld infos. Return true if we actually read anything,
-// and false otherwise.
+// If we have found where the "_dyld_all_image_infos" lives in memory, read the
+// current info from it, and then update all image load addresses (or lack
+// thereof). Only do this if this is the first time we're reading the dyld
+// infos. Return true if we actually read anything, and false otherwise.
//----------------------------------------------------------------------
bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() {
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
@@ -748,14 +738,11 @@ bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() {
}
// Now we have one more bit of business. If there is a library left in the
- // images for our target that
- // doesn't have a load address, then it must be something that we were
- // expecting to load (for instance we
- // read a load command for it) but it didn't in fact load - probably because
- // DYLD_*_PATH pointed
- // to an equivalent version. We don't want it to stay in the target's
- // module list or it will confuse
- // us, so unload it here.
+ // images for our target that doesn't have a load address, then it must be
+ // something that we were expecting to load (for instance we read a load
+ // command for it) but it didn't in fact load - probably because
+ // DYLD_*_PATH pointed to an equivalent version. We don't want it to stay
+ // in the target's module list or it will confuse us, so unload it here.
Target &target = m_process->GetTarget();
const ModuleList &target_modules = target.GetImages();
ModuleList not_loaded_modules;
@@ -784,8 +771,8 @@ bool DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos() {
}
//----------------------------------------------------------------------
-// Read a mach_header at ADDR into HEADER, and also fill in the load
-// command data into LOAD_COMMAND_DATA if it is non-NULL.
+// Read a mach_header at ADDR into HEADER, and also fill in the load command
+// data into LOAD_COMMAND_DATA if it is non-NULL.
//
// Returns true if we succeed, false if we fail for any reason.
//----------------------------------------------------------------------
@@ -840,8 +827,8 @@ bool DynamicLoaderMacOSXDYLD::ReadMachHeader(lldb::addr_t addr,
load_cmd_data_sp->GetByteSize(), error);
if (load_cmd_bytes_read == header->sizeofcmds) {
- // Set the load command data and also set the correct endian
- // swap settings and the correct address size
+ // Set the load command data and also set the correct endian swap
+ // settings and the correct address size
load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds);
load_command_data->SetByteOrder(data.GetByteOrder());
load_command_data->SetAddressByteSize(data.GetAddressByteSize());
@@ -867,8 +854,8 @@ uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
dylib_info.Clear(true);
for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) {
- // Clear out any load command specific data from DYLIB_INFO since
- // we are about to read it.
+ // Clear out any load command specific data from DYLIB_INFO since we are
+ // about to read it.
if (data.ValidOffsetForDataOfSize(offset,
sizeof(llvm::MachO::load_command))) {
@@ -880,8 +867,8 @@ uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
case llvm::MachO::LC_SEGMENT: {
segment.name.SetTrimmedCStringWithLength(
(const char *)data.GetData(&offset, 16), 16);
- // We are putting 4 uint32_t values 4 uint64_t values so
- // we have to use multiple 32 bit gets below.
+ // We are putting 4 uint32_t values 4 uint64_t values so we have to use
+ // multiple 32 bit gets below.
segment.vmaddr = data.GetU32(&offset);
segment.vmsize = data.GetU32(&offset);
segment.fileoff = data.GetU32(&offset);
@@ -906,12 +893,12 @@ uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
const lldb::offset_t name_offset =
load_cmd_offset + data.GetU32(&offset);
const char *path = data.PeekCStr(name_offset);
- lc_id_dylinker->SetFile(path, true);
+ lc_id_dylinker->SetFile(path, true, FileSpec::Style::native);
}
break;
case llvm::MachO::LC_UUID:
- dylib_info.uuid.SetBytes(data.GetData(&offset, 16));
+ dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16);
break;
default:
@@ -922,24 +909,21 @@ uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
}
}
- // All sections listed in the dyld image info structure will all
- // either be fixed up already, or they will all be off by a single
- // slide amount that is determined by finding the first segment
- // that is at file offset zero which also has bytes (a file size
- // that is greater than zero) in the object file.
+ // All sections listed in the dyld image info structure will all either be
+ // fixed up already, or they will all be off by a single slide amount that is
+ // determined by finding the first segment that is at file offset zero which
+ // also has bytes (a file size that is greater than zero) in the object file.
// Determine the slide amount (if any)
const size_t num_sections = dylib_info.segments.size();
for (size_t i = 0; i < num_sections; ++i) {
- // Iterate through the object file sections to find the
- // first section that starts of file offset zero and that
- // has bytes in the file...
+ // Iterate through the object file sections to find the first section that
+ // starts of file offset zero and that has bytes in the file...
if ((dylib_info.segments[i].fileoff == 0 &&
dylib_info.segments[i].filesize > 0) ||
(dylib_info.segments[i].name == ConstString("__TEXT"))) {
dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr;
- // We have found the slide amount, so we can exit
- // this for loop.
+ // We have found the slide amount, so we can exit this for loop.
break;
}
}
@@ -984,11 +968,11 @@ void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(
// Don't load dependent images since we are in dyld where we will know
// and find out about all images that are loaded. Also when setting the
// executable module, it will clear the targets module list, and if we
- // have an in memory dyld module, it will get removed from the list
- // so we will need to add it back after setting the executable module,
- // so we first try and see if we already have a weak pointer to the
- // dyld module, make it into a shared pointer, then add the executable,
- // then re-add it back to make sure it is always in the list.
+ // have an in memory dyld module, it will get removed from the list so
+ // we will need to add it back after setting the executable module, so
+ // we first try and see if we already have a weak pointer to the dyld
+ // module, make it into a shared pointer, then add the executable, then
+ // re-add it back to make sure it is always in the list.
ModuleSP dyld_module_sp(GetDYLDModule());
const bool get_dependent_images = false;
@@ -1009,8 +993,8 @@ void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(
}
//----------------------------------------------------------------------
-// Dump the _dyld_all_image_infos members and all current image infos
-// that we have parsed to the file handle provided.
+// Dump the _dyld_all_image_infos members and all current image infos that we
+// have parsed to the file handle provided.
//----------------------------------------------------------------------
void DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const {
if (log == NULL)
@@ -1039,10 +1023,9 @@ bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint() {
if (m_break_id == LLDB_INVALID_BREAK_ID) {
if (m_dyld_all_image_infos.notification != LLDB_INVALID_ADDRESS) {
Address so_addr;
- // Set the notification breakpoint and install a breakpoint
- // callback function that will get called each time the
- // breakpoint gets hit. We will use this to track when shared
- // libraries get loaded/unloaded.
+ // Set the notification breakpoint and install a breakpoint callback
+ // function that will get called each time the breakpoint gets hit. We
+ // will use this to track when shared libraries get loaded/unloaded.
bool resolved = m_process->GetTarget().ResolveLoadAddress(
m_dyld_all_image_infos.notification, so_addr);
if (!resolved) {
@@ -1071,9 +1054,9 @@ bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint() {
Status DynamicLoaderMacOSXDYLD::CanLoadImage() {
Status error;
- // In order for us to tell if we can load a shared library we verify that
- // the dylib_info_addr isn't zero (which means no shared libraries have
- // been set yet, or dyld is currently mucking with the shared library list).
+ // In order for us to tell if we can load a shared library we verify that the
+ // dylib_info_addr isn't zero (which means no shared libraries have been set
+ // yet, or dyld is currently mucking with the shared library list).
if (ReadAllImageInfosStructure()) {
// TODO: also check the _dyld_global_lock_held variable in
// libSystem.B.dylib?
@@ -1099,13 +1082,10 @@ bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation(
addr_t all_image_infos = m_process->GetImageInfoAddress();
// The address returned by GetImageInfoAddress may be the address of dyld
- // (don't want)
- // or it may be the address of the dyld_all_image_infos structure (want).
- // The first four
- // bytes will be either the version field (all_image_infos) or a Mach-O file
- // magic constant.
- // Version 13 and higher of dyld_all_image_infos is required to get the
- // sharedCacheUUID field.
+ // (don't want) or it may be the address of the dyld_all_image_infos
+ // structure (want). The first four bytes will be either the version field
+ // (all_image_infos) or a Mach-O file magic constant. Version 13 and higher
+ // of dyld_all_image_infos is required to get the sharedCacheUUID field.
Status err;
uint32_t version_or_magic =
@@ -1130,7 +1110,7 @@ bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation(
uuid_t shared_cache_uuid;
if (m_process->ReadMemory(sharedCacheUUID_address, shared_cache_uuid,
sizeof(uuid_t), err) == sizeof(uuid_t)) {
- uuid.SetBytes(shared_cache_uuid);
+ uuid = UUID::fromOptionalData(shared_cache_uuid, 16);
if (uuid.IsValid()) {
using_shared_cache = eLazyBoolYes;
}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
index cf9da0808357..3b06fe18f0c6 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
@@ -22,12 +22,12 @@ class DataExtractor;
}
/// @class AuxVector
-/// @brief Represents a processes auxiliary vector.
+/// Represents a processes auxiliary vector.
///
/// When a process is loaded on Linux a vector of values is placed onto the
-/// stack communicating operating system specific information. On construction
-/// this class locates and parses this information and provides a simple
-/// read-only interface to the entries found.
+/// stack communicating operating system specific information. On
+/// construction this class locates and parses this information and provides a
+/// simple read-only interface to the entries found.
class AuxVector {
public:
@@ -41,8 +41,9 @@ public:
};
/// Constants describing the type of entry.
- /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information.
- /// Added AUXV prefix to avoid potential conflicts with system-defined macros
+ /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX
+ /// information. Added AUXV prefix to avoid potential conflicts with system-
+ /// defined macros
enum EntryType {
AUXV_AT_NULL = 0, ///< End of auxv.
AUXV_AT_IGNORE = 1, ///< Ignore entry.
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index e601d64f0d8d..b1513b51a90a 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -45,8 +45,8 @@ static addr_t ResolveRendezvousAddress(Process *process) {
if (log)
log->Printf("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);
- // If the process fails to return an address, fall back to seeing if the local
- // object file can help us find it.
+ // If the process fails to return an address, fall back to seeing if the
+ // local object file can help us find it.
if (info_location == LLDB_INVALID_ADDRESS) {
Target *target = &process->GetTarget();
if (target) {
@@ -190,8 +190,8 @@ bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) {
if (!fromRemote && m_current.map_addr == 0)
return false;
- // When the previous and current states are consistent this is the first
- // time we have been asked to update. Just take a snapshot of the currently
+ // When the previous and current states are consistent this is the first time
+ // we have been asked to update. Just take a snapshot of the currently
// loaded modules.
if (m_previous.state == eConsistent && m_current.state == eConsistent)
return fromRemote ? SaveSOEntriesFromRemote(module_list)
@@ -200,9 +200,9 @@ bool DYLDRendezvous::UpdateSOEntries(bool fromRemote) {
// If we are about to add or remove a shared object clear out the current
// state and take a snapshot of the currently loaded images.
if (m_current.state == eAdd || m_current.state == eDelete) {
- // Some versions of the android dynamic linker might send two
- // notifications with state == eAdd back to back. Ignore them
- // until we get an eConsistent notification.
+ // Some versions of the android dynamic linker might send two notifications
+ // with state == eAdd back to back. Ignore them until we get an eConsistent
+ // notification.
if (!(m_previous.state == eConsistent ||
(m_previous.state == eAdd && m_current.state == eDelete)))
return false;
@@ -243,7 +243,7 @@ bool DYLDRendezvous::FillSOEntryFromModuleInfo(
entry.base_addr = base_addr;
entry.dyn_addr = dyn_addr;
- entry.file_spec.SetFile(name, false);
+ entry.file_spec.SetFile(name, false, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, name);
@@ -449,16 +449,13 @@ std::string DYLDRendezvous::ReadStringFromMemory(addr_t addr) {
}
// 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.
+// 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;
+ // isn't filled in correctly.
+ unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();
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")) {
@@ -471,8 +468,7 @@ static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,
std::string const &file_path) {
// If the load bias reported by the linker is incorrect then fetch the load
- // address of the file
- // from the proc file system.
+ // 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;
@@ -491,8 +487,8 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
if (!(addr = ReadPointer(addr, &entry.base_addr)))
return false;
- // mips adds an extra load offset field to the link map struct on
- // FreeBSD and NetBSD (need to validate other OSes).
+ // mips adds an extra load offset field to the link map struct on FreeBSD and
+ // NetBSD (need to validate other OSes).
// http://svnweb.freebsd.org/base/head/sys/sys/link_elf.h?revision=217153&view=markup#l57
const ArchSpec &arch = m_process->GetTarget().GetArchitecture();
if ((arch.GetTriple().getOS() == llvm::Triple::FreeBSD ||
@@ -521,7 +517,7 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
return false;
std::string file_path = ReadStringFromMemory(entry.path_addr);
- entry.file_spec.SetFile(file_path, false);
+ entry.file_spec.SetFile(file_path, false, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, file_path);
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index 295ae55e1b85..a7071801f569 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -29,12 +29,12 @@ class Process;
}
/// @class DYLDRendezvous
-/// @brief Interface to the runtime linker.
+/// Interface to the runtime linker.
///
/// A structure is present in a processes memory space which is updated by the
-/// runtime liker each time a module is loaded or unloaded. This class provides
-/// an interface to this structure and maintains a consistent snapshot of the
-/// currently loaded modules.
+/// runtime liker each time a module is loaded or unloaded. This class
+/// provides an interface to this structure and maintains a consistent
+/// snapshot of the currently loaded modules.
class DYLDRendezvous {
// This structure is used to hold the contents of the debug rendezvous
@@ -119,13 +119,13 @@ public:
void DumpToLog(lldb_private::Log *log) const;
- /// @brief Constants describing the state of the rendezvous.
+ /// Constants describing the state of the rendezvous.
///
/// @see GetState().
enum RendezvousState { eConsistent, eAdd, eDelete };
- /// @brief Structure representing the shared objects currently loaded into
- /// the inferior process.
+ /// Structure representing the shared objects currently loaded into the
+ /// inferior process.
///
/// This object is a rough analogue to the struct link_map object which
/// actually lives in the inferiors memory.
@@ -194,7 +194,8 @@ protected:
/// List of SOEntry objects corresponding to the current link map state.
SOEntryList m_soentries;
- /// List of SOEntry's added to the link map since the last call to Resolve().
+ /// List of SOEntry's added to the link map since the last call to
+ /// Resolve().
SOEntryList m_added_soentries;
/// List of SOEntry's removed from the link map since the last call to
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index a7afeb6d68c3..26825d879f04 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -79,7 +79,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
: DynamicLoader(process), m_rendezvous(process),
m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS),
m_auxv(), m_dyld_bid(LLDB_INVALID_BREAK_ID),
- m_vdso_base(LLDB_INVALID_ADDRESS) {}
+ m_vdso_base(LLDB_INVALID_ADDRESS),
+ m_interpreter_base(LLDB_INVALID_ADDRESS) {}
DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD() {
if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
@@ -117,7 +118,7 @@ void DynamicLoaderPOSIXDYLD::DidAttach() {
: "<null executable>",
load_offset);
- EvalVdsoStatus();
+ EvalSpecialModulesStatus();
// if we dont have a load address we cant re-base
bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true;
@@ -152,31 +153,10 @@ void DynamicLoaderPOSIXDYLD::DidAttach() {
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
- // structure is ready to be used and we can load the list of modules
- // and place the rendezvous breakpoint.
- // (2) We didn't cross the entry point yet, so these structures are not
- // ready; we should behave as if we just launched the target and
- // call ProbeEntry(). This will place a breakpoint on the entry
- // point which itself will be hit after the rendezvous structure is
- // set up and will perform actions described in (1).
- if (m_rendezvous.Resolve()) {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64
- " rendezvous could resolve: attach assuming dynamic loader "
- "info is available now",
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
- LoadAllCurrentModules();
- SetRendezvousBreakpoint();
- } else {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s() pid %" PRIu64
- " rendezvous could not yet resolve: adding breakpoint to "
- "catch future rendezvous setup",
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+ LoadAllCurrentModules();
+ if (!SetRendezvousBreakpoint()) {
+ // If we cannot establish rendezvous breakpoint right now we'll try again
+ // at entry point.
ProbeEntry();
}
@@ -207,7 +187,7 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() {
executable = GetTargetExecutable();
load_offset = ComputeLoadOffset();
- EvalVdsoStatus();
+ EvalSpecialModulesStatus();
if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) {
ModuleList module_list;
@@ -217,8 +197,14 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() {
if (log)
log->Printf("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()",
__FUNCTION__);
- ProbeEntry();
+ if (!SetRendezvousBreakpoint()) {
+ // If we cannot establish rendezvous breakpoint right now we'll try again
+ // at entry point.
+ ProbeEntry();
+ }
+
+ LoadVDSO();
m_process->GetTarget().ModulesDidLoad(module_list);
}
}
@@ -273,11 +259,11 @@ void DynamicLoaderPOSIXDYLD::ProbeEntry() {
}
// The runtime linker has run and initialized the rendezvous structure once the
-// process has hit its entry point. When we hit the corresponding breakpoint we
-// interrogate the rendezvous structure to get the load addresses of all
+// process has hit its entry point. When we hit the corresponding breakpoint
+// we interrogate the rendezvous structure to get the load addresses of all
// dependent modules for the process. Similarly, we can discover the runtime
-// linker function and setup a breakpoint to notify us of any dynamically loaded
-// modules (via dlopen).
+// linker function and setup a breakpoint to notify us of any dynamically
+// loaded modules (via dlopen).
bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
void *baton, StoppointCallbackContext *context, user_id_t break_id,
user_id_t break_loc_id) {
@@ -295,13 +281,11 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
: LLDB_INVALID_PROCESS_ID);
// Disable the breakpoint --- if a stop happens right after this, which we've
- // seen on occasion, we don't
- // want the breakpoint stepping thread-plan logic to show a breakpoint
- // instruction at the disassembled
- // entry point to the program. Disabling it prevents it. (One-shot is not
- // enough - one-shot removal logic
- // only happens after the breakpoint goes public, which wasn't happening in
- // our scenario).
+ // seen on occasion, we don't want the breakpoint stepping thread-plan logic
+ // to show a breakpoint instruction at the disassembled entry point to the
+ // program. Disabling it prevents it. (One-shot is not enough - one-shot
+ // removal logic only happens after the breakpoint goes public, which wasn't
+ // happening in our scenario).
if (dyld_instance->m_process) {
BreakpointSP breakpoint_sp =
dyld_instance->m_process->GetTarget().GetBreakpointByID(break_id);
@@ -329,38 +313,77 @@ bool DynamicLoaderPOSIXDYLD::EntryBreakpointHit(
return false; // Continue running.
}
-void DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {
+bool DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint() {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (m_dyld_bid != LLDB_INVALID_BREAK_ID) {
+ LLDB_LOG(log,
+ "Rendezvous breakpoint breakpoint id {0} for pid {1}"
+ "is already set.",
+ m_dyld_bid,
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+ return true;
+ }
- addr_t break_addr = m_rendezvous.GetBreakAddress();
+ addr_t break_addr;
Target &target = m_process->GetTarget();
-
- if (m_dyld_bid == LLDB_INVALID_BREAK_ID) {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
- " setting rendezvous break address at 0x%" PRIx64,
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
- break_addr);
- Breakpoint *dyld_break =
- target.CreateBreakpoint(break_addr, true, false).get();
- dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
- dyld_break->SetBreakpointKind("shared-library-event");
- m_dyld_bid = dyld_break->GetID();
+ BreakpointSP dyld_break;
+ if (m_rendezvous.IsValid()) {
+ break_addr = m_rendezvous.GetBreakAddress();
+ LLDB_LOG(log, "Setting rendezvous break address for pid {0} at {1:x}",
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
+ break_addr);
+ dyld_break = target.CreateBreakpoint(break_addr, true, false);
} else {
- if (log)
- log->Printf("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64
- " reusing break id %" PRIu32 ", address at 0x%" PRIx64,
- __FUNCTION__,
- m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID,
- m_dyld_bid, break_addr);
+ LLDB_LOG(log, "Rendezvous structure is not set up yet. "
+ "Trying to locate rendezvous breakpoint in the interpreter "
+ "by symbol name.");
+ ModuleSP interpreter = LoadInterpreterModule();
+ if (!interpreter) {
+ LLDB_LOG(log, "Can't find interpreter, rendezvous breakpoint isn't set.");
+ return false;
+ }
+
+ // Function names from different dynamic loaders that are known to be used
+ // as rendezvous between the loader and debuggers.
+ static std::vector<std::string> DebugStateCandidates{
+ "_dl_debug_state", "rtld_db_dlactivity", "__dl_rtld_db_dlactivity",
+ "r_debug_state", "_r_debug_state", "_rtld_debug_state",
+ };
+
+ FileSpecList containingModules;
+ containingModules.Append(interpreter->GetFileSpec());
+ dyld_break = target.CreateBreakpoint(
+ &containingModules, nullptr /* containingSourceFiles */,
+ DebugStateCandidates, eFunctionNameTypeFull, eLanguageTypeC,
+ 0, /* offset */
+ eLazyBoolNo, /* skip_prologue */
+ true, /* internal */
+ false /* request_hardware */);
+ }
+
+ if (dyld_break->GetNumResolvedLocations() != 1) {
+ LLDB_LOG(
+ log,
+ "Rendezvous breakpoint has abnormal number of"
+ " resolved locations ({0}) in pid {1}. It's supposed to be exactly 1.",
+ dyld_break->GetNumResolvedLocations(),
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+
+ target.RemoveBreakpointByID(dyld_break->GetID());
+ return false;
}
- // Make sure our breakpoint is at the right address.
- assert(target.GetBreakpointByID(m_dyld_bid)
- ->FindLocationByAddress(break_addr)
- ->GetBreakpoint()
- .GetID() == m_dyld_bid);
+ BreakpointLocationSP location = dyld_break->GetLocationAtIndex(0);
+ LLDB_LOG(log,
+ "Successfully set rendezvous breakpoint at address {0:x} "
+ "for pid {1}",
+ location->GetLoadAddress(),
+ m_process ? m_process->GetID() : LLDB_INVALID_PROCESS_ID);
+
+ dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+ dyld_break->SetBreakpointKind("shared-library-event");
+ m_dyld_bid = dyld_break->GetID();
+ return true;
}
bool DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(
@@ -485,7 +508,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
return thread_plan_sp;
}
-void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) {
+void DynamicLoaderPOSIXDYLD::LoadVDSO() {
if (m_vdso_base == LLDB_INVALID_ADDRESS)
return;
@@ -506,13 +529,40 @@ void DynamicLoaderPOSIXDYLD::LoadVDSO(ModuleList &modules) {
}
}
+ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
+ if (m_interpreter_base == LLDB_INVALID_ADDRESS)
+ return nullptr;
+
+ MemoryRegionInfo info;
+ Target &target = m_process->GetTarget();
+ Status status = m_process->GetMemoryRegionInfo(m_interpreter_base, info);
+ if (status.Fail() || info.GetMapped() != MemoryRegionInfo::eYes ||
+ info.GetName().IsEmpty()) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ LLDB_LOG(log, "Failed to get interpreter region info: {0}", status);
+ return nullptr;
+ }
+
+ FileSpec file(info.GetName().GetCString(), false);
+ ModuleSpec module_spec(file, target.GetArchitecture());
+
+ if (ModuleSP module_sp = target.GetSharedModule(module_spec)) {
+ UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base,
+ false);
+ return module_sp;
+ }
+ return nullptr;
+}
+
void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
DYLDRendezvous::iterator I;
DYLDRendezvous::iterator E;
ModuleList module_list;
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+ LoadVDSO();
if (!m_rendezvous.Resolve()) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
log->Printf("DynamicLoaderPOSIXDYLD::%s unable to resolve POSIX DYLD "
"rendezvous address",
@@ -520,11 +570,10 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
return;
}
- // The rendezvous class doesn't enumerate the main module, so track
- // that ourselves here.
+ // The rendezvous class doesn't enumerate the main module, so track that
+ // ourselves here.
ModuleSP executable = GetTargetExecutable();
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
- LoadVDSO(module_list);
std::vector<FileSpec> module_names;
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
@@ -536,6 +585,8 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
ModuleSP module_sp =
LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get()) {
+ LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}",
+ I->file_spec.GetFilename());
module_list.Append(module_sp);
} else {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
@@ -575,11 +626,14 @@ addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() {
return m_load_offset;
}
-void DynamicLoaderPOSIXDYLD::EvalVdsoStatus() {
- AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR);
-
- if (I != m_auxv->end())
+void DynamicLoaderPOSIXDYLD::EvalSpecialModulesStatus() {
+ auto I = m_auxv->FindEntry(AuxVector::AUXV_AT_SYSINFO_EHDR);
+ if (I != m_auxv->end() && I->value != 0)
m_vdso_base = I->value;
+
+ I = m_auxv->FindEntry(AuxVector::AUXV_AT_BASE);
+ if (I != m_auxv->end() && I->value != 0)
+ m_interpreter_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 2e9670587e66..0456baf4a658 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -85,13 +85,17 @@ protected:
/// mapped to the address space
lldb::addr_t m_vdso_base;
+ /// Contains AT_BASE, which means a dynamic loader has been
+ /// mapped to the address space
+ lldb::addr_t m_interpreter_base;
+
/// Loaded module list. (link map for each module)
std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>>
m_loaded_modules;
- /// Enables a breakpoint on a function called by the runtime
+ /// If possible sets a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
- virtual void SetRendezvousBreakpoint();
+ bool SetRendezvousBreakpoint();
/// Callback routine which updates the current list of loaded modules based
/// on the information supplied by the runtime linker.
@@ -138,7 +142,11 @@ protected:
/// of all dependent modules.
virtual void LoadAllCurrentModules();
- void LoadVDSO(lldb_private::ModuleList &modules);
+ void LoadVDSO();
+
+ // Loading an interpreter module (if present) assumming m_interpreter_base
+ // already points to its base address.
+ lldb::ModuleSP LoadInterpreterModule();
/// Computes a value for m_load_offset returning the computed address on
/// success and LLDB_INVALID_ADDRESS on failure.
@@ -148,9 +156,10 @@ protected:
/// success and LLDB_INVALID_ADDRESS on failure.
lldb::addr_t GetEntryPoint();
- /// Evaluate if Aux vectors contain vDSO information
+ /// Evaluate if Aux vectors contain vDSO and LD information
/// in case they do, read and assign the address to m_vdso_base
- void EvalVdsoStatus();
+ /// and m_interpreter_base.
+ void EvalSpecialModulesStatus();
/// Loads Module from inferior process.
void ResolveExecutableModule(lldb::ModuleSP &module_sp);
diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
index 291695cb68c1..2960e3939461 100644
--- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
+++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
@@ -19,9 +19,9 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// Create an instance of this class. This function is filled into
-// the plugin info class that gets handed out by the plugin factory and
-// allows the lldb to instantiate an instance of this class.
+// Create an instance of this class. This function is filled into the plugin
+// info class that gets handed out by the plugin factory and allows the lldb to
+// instantiate an instance of this class.
//----------------------------------------------------------------------
DynamicLoader *DynamicLoaderStatic::CreateInstance(Process *process,
bool force) {
@@ -97,17 +97,17 @@ void DynamicLoaderStatic::LoadAllImagesAtFileAddresses() {
if (section_list) {
// All sections listed in the dyld image info structure will all
// either be fixed up already, or they will all be off by a single
- // slide amount that is determined by finding the first segment
- // that is at file offset zero which also has bytes (a file size
- // that is greater than zero) in the object file.
+ // slide amount that is determined by finding the first segment that
+ // is at file offset zero which also has bytes (a file size that is
+ // greater than zero) in the object file.
// Determine the slide amount (if any)
const size_t num_sections = section_list->GetSize();
size_t sect_idx = 0;
for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find the
- // first section that starts of file offset zero and that
- // has bytes in the file...
+ // Iterate through the object file sections to find the first
+ // section that starts of file offset zero and that has bytes in
+ // the file...
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp) {
if (m_process->GetTarget().SetSectionLoadAddress(
diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index 9e6a2f3acafe..fa49a51f32a6 100644
--- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -226,8 +226,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
return true;
// In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off
- // if that's the
- // case.
+ // if that's the case.
do {
ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
@@ -242,8 +241,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
} 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.
+ // Lvalue or an Rvalue. This is relevant because they are handled
+ // differently.
//
// For Lvalues
//
@@ -293,9 +292,8 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
//
// - During dematerialization, $0 is ignored.
- bool is_lvalue = (last_expr->getValueKind() == VK_LValue ||
- last_expr->getValueKind() == VK_XValue) &&
- (last_expr->getObjectKind() == OK_Ordinary);
+ bool is_lvalue = last_expr->getValueKind() == VK_LValue &&
+ last_expr->getObjectKind() == OK_Ordinary;
QualType expr_qual_type = last_expr->getType();
const clang::Type *expr_type = expr_qual_type.getTypePtr();
diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
index c0e6c0358a23..859a1dfa5f73 100644
--- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
+++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
@@ -18,18 +18,17 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ASTResultSynthesizer ASTResultSynthesizer.h
-/// "lldb/Expression/ASTResultSynthesizer.h"
-/// @brief Adds a result variable declaration to the ASTs for an expression.
+/// "lldb/Expression/ASTResultSynthesizer.h" 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
+/// 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.
+/// 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:
@@ -68,8 +67,8 @@ public:
void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
- /// Examine a list of Decls to find the function $__lldb_expr and
- /// transform its code
+ /// 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,
@@ -124,8 +123,8 @@ public:
private:
//----------------------------------------------------------------------
- /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing
- /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on
+ /// 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
@@ -164,8 +163,8 @@ private:
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.
+ /// 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.
@@ -173,8 +172,8 @@ private:
void RecordPersistentTypes(clang::DeclContext *FunDeclCtx);
//----------------------------------------------------------------------
- /// Given a TypeDecl, if it declares a type whose name starts with a
- /// dollar sign, register it as a pointer type in the target's scratch
+ /// 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
diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
index 63e3161cae85..65f4b00a8651 100644
--- a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
+++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
@@ -20,20 +20,19 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ASTStructExtractor ASTStructExtractor.h
-/// "lldb/Expression/ASTStructExtractor.h"
-/// @brief Extracts and describes the argument structure for a wrapped function.
+/// "lldb/Expression/ASTStructExtractor.h" 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.
+/// 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.
+/// 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:
@@ -73,8 +72,8 @@ public:
void Initialize(clang::ASTContext &Context) override;
//----------------------------------------------------------------------
- /// Examine a list of Decls to find the function $__lldb_expr and
- /// transform its code
+ /// 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,
diff --git a/source/Plugins/ExpressionParser/Clang/CMakeLists.txt b/source/Plugins/ExpressionParser/Clang/CMakeLists.txt
index a780e7d597b1..ec4f6d5674e1 100644
--- a/source/Plugins/ExpressionParser/Clang/CMakeLists.txt
+++ b/source/Plugins/ExpressionParser/Clang/CMakeLists.txt
@@ -11,6 +11,7 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN
ClangExpressionParser.cpp
ClangExpressionVariable.cpp
ClangFunctionCaller.cpp
+ ClangHost.cpp
ClangModulesDeclVendor.cpp
ClangPersistentVariables.cpp
ClangUserExpression.cpp
@@ -23,6 +24,7 @@ add_lldb_library(lldbPluginExpressionParserClang PLUGIN
LINK_LIBS
clangAST
clangCodeGen
+ clangDriver
clangEdit
clangFrontend
clangLex
diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 7f031356b3c3..d98a2b25fbb7 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -33,8 +33,8 @@ 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.
+// Scoped class that will remove an active lexical decl from the set when it
+// goes out of scope.
//------------------------------------------------------------------
namespace {
class ScopedLexicalDeclEraser {
@@ -141,8 +141,8 @@ 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).
+ // demand by passing false to
+ // Target::GetScratchClangASTContext(create_on_demand).
ClangASTContext *scratch_clang_ast_context =
m_target->GetScratchClangASTContext(false);
@@ -231,8 +231,8 @@ bool ClangASTSource::FindExternalVisibleDeclsByName(
}
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.
+ // 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 {
@@ -297,8 +297,8 @@ void ClangASTSource::CompleteType(TagDecl *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.
+ // 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 "
@@ -398,8 +398,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
const_cast<TagDecl *>(tag_type->getDecl());
// We have found a type by basename and we need to make sure the decl
- // contexts
- // are the same before we can try to complete this type with another
+ // contexts are the same before we can try to complete this type with
+ // another
if (!ClangASTContext::DeclsAreEquivalent(tag_decl, candidate_tag_decl))
continue;
@@ -861,13 +861,16 @@ void ClangASTSource::FindExternalVisibleDecls(
TypeList types;
SymbolContext null_sc;
- const bool exact_match = false;
+ const bool exact_match = true;
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
if (module_sp && namespace_decl)
module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
- else
- m_target->GetImages().FindTypes(null_sc, name, exact_match, 1,
+ else {
+ SymbolContext sc;
+ sc.module_sp = module_sp;
+ m_target->GetImages().FindTypes(sc, name, exact_match, 1,
searched_symbol_files, types);
+ }
if (size_t num_types = types.GetSize()) {
for (size_t ti = 0; ti < num_types; ++ti) {
@@ -1243,8 +1246,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
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.
+ // way, we need to check that they're actually in categories on the desired
+ // class.
SymbolContextList candidate_sc_list;
@@ -1591,8 +1594,7 @@ void ClangASTSource::FindObjCPropertyAndIvarDecls(NameSearchContext &context) {
do {
// Check the runtime only if the debug information didn't have a complete
- // interface
- // and nothing was in the modules.
+ // interface and nothing was in the modules.
lldb::ProcessSP process(m_target->GetProcessSP());
@@ -1645,12 +1647,9 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map,
ClangASTSource &source) {
// 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.
+ // DenseMap with a pointer as the key type, this means we cannot simply
+ // iterate over the map, as the order will be non-deterministic. Instead we
+ // have to sort by the offset and then insert in sorted order.
typedef llvm::DenseMap<const D *, O> MapType;
typedef typename MapType::value_type PairType;
std::vector<PairType> sorted_items;
@@ -2051,9 +2050,8 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) {
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.
+ // 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);
@@ -2156,6 +2154,18 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
log->Printf("Function type wasn't a FunctionProtoType");
}
+ // If this is an operator (e.g. operator new or operator==), only insert the
+ // declaration we inferred from the symbol if we can provide the correct
+ // number of arguments. We shouldn't really inject random decl(s) for
+ // functions that are analyzed semantically in a special way, otherwise we
+ // will crash in clang.
+ clang::OverloadedOperatorKind op_kind = clang::NUM_OVERLOADED_OPERATORS;
+ if (func_proto_type &&
+ ClangASTContext::IsOperator(decl_name.getAsString().c_str(), op_kind)) {
+ if (!ClangASTContext::CheckOverloadedOperatorKindParameterCount(
+ false, op_kind, func_proto_type->getNumParams()))
+ return NULL;
+ }
m_decls.push_back(func_decl);
return func_decl;
diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 6f72ad92dc8c..a42422b0f97f 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -25,14 +25,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h"
-/// @brief Provider for named objects defined in the debug info for Clang
+/// 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.
+/// 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 {
@@ -78,8 +77,8 @@ public:
//------------------------------------------------------------------
/// 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.
+ /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with the
+ /// result.
///
/// The work for this function is done by
/// void FindExternalVisibleDecls (NameSearchContext &);
@@ -173,8 +172,8 @@ public:
//------------------------------------------------------------------
/// Called on entering a translation unit. Tells Clang by calling
- /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage()
- /// that this object has something to say about undefined names.
+ /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that
+ /// this object has something to say about undefined names.
///
/// @param[in] ASTConsumer
/// Unused.
@@ -186,8 +185,8 @@ public:
//
//------------------------------------------------------------------
- /// Look up the modules containing a given namespace and put the
- /// appropriate entries in the namespace map.
+ /// 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.
@@ -231,11 +230,10 @@ public:
//----------------------------------------------------------------------
/// @class ClangASTSourceProxy ClangASTSource.h
- /// "lldb/Expression/ClangASTSource.h"
- /// @brief Proxy for ClangASTSource
+ /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource
///
- /// Clang AST contexts like to own their AST sources, so this is a
- /// state-free proxy object.
+ /// Clang AST contexts like to own their AST sources, so this is a state-
+ /// free proxy object.
//----------------------------------------------------------------------
class ClangASTSourceProxy : public ClangExternalASTSourceCommon {
public:
@@ -298,8 +296,8 @@ public:
protected:
//------------------------------------------------------------------
- /// Look for the complete version of an Objective-C interface, and
- /// return it if found.
+ /// 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.
@@ -312,8 +310,8 @@ protected:
GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl);
//------------------------------------------------------------------
- /// Find all entities matching a given name in a given module,
- /// using a NameSearchContext to make Decls for them.
+ /// 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.
@@ -474,8 +472,9 @@ protected:
};
//----------------------------------------------------------------------
-/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h"
-/// @brief Container for all objects relevant to a single name lookup
+/// @class NameSearchContext ClangASTSource.h
+/// "lldb/Expression/ClangASTSource.h" 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
@@ -532,8 +531,8 @@ struct NameSearchContext {
}
//------------------------------------------------------------------
- /// Create a VarDecl with the name being searched for and the provided
- /// type and register it in the right places.
+ /// 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.
@@ -541,8 +540,8 @@ struct NameSearchContext {
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.
+ /// 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.
@@ -553,15 +552,14 @@ struct NameSearchContext {
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.
+ /// 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.
+ /// 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.
@@ -569,8 +567,8 @@ struct NameSearchContext {
clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type);
//------------------------------------------------------------------
- /// Add Decls from the provided DeclContextLookupResult to the list
- /// of results.
+ /// Add Decls from the provided DeclContextLookupResult to the list of
+ /// results.
///
/// @param[in] result
/// The DeclContextLookupResult, usually returned as the result
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 07ff2e97aac7..0811a7999920 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -213,8 +213,8 @@ private:
m_exporter.getFromContext().getSourceManager().getFileID(loc);
if (file != m_file)
return false;
- // We are assuming the Decl was parsed in this very expression, so it should
- // not have external storage.
+ // We are assuming the Decl was parsed in this very expression, so it
+ // should not have external storage.
lldbassert(!llvm::cast<DeclContext>(decl)->hasExternalLexicalStorage());
return true;
}
@@ -591,8 +591,8 @@ bool ClangExpressionDeclMap::GetFunctionInfo(const NamedDecl *decl,
if (!entity)
return false;
- // We know m_parser_vars is valid since we searched for the variable by
- // its NamedDecl
+ // We know m_parser_vars is valid since we searched for the variable by its
+ // NamedDecl
ClangExpressionVariable::ParserVars *parser_vars =
entity->GetParserVars(GetParserID());
@@ -720,9 +720,9 @@ lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
VariableList vars;
if (module && namespace_decl)
- module->FindGlobalVariables(name, namespace_decl, true, -1, vars);
+ module->FindGlobalVariables(name, namespace_decl, -1, vars);
else
- target.GetImages().FindGlobalVariables(name, true, -1, vars);
+ target.GetImages().FindGlobalVariables(name, -1, vars);
if (vars.GetSize()) {
if (type) {
@@ -867,8 +867,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
if (IgnoreName(name, false))
return;
- // Only look for functions by name out in our symbols if the function
- // doesn't start with our phony prefix of '$'
+ // 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;
@@ -977,13 +977,11 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
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.
+ // 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.
@@ -1093,13 +1091,11 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
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.
+ // 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);
@@ -1217,9 +1213,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
vars->GetVariableAtIndex(i)->GetDecl();
// Search for declarations matching the name. Do not include imported
- // decls
- // in the search if we are looking for decls in the artificial namespace
- // $__lldb_local_vars.
+ // decls in the search if we are looking for decls in the artificial
+ // namespace $__lldb_local_vars.
std::vector<CompilerDecl> found_decls =
compiler_decl_context.FindDeclByName(name,
namespace_decl.IsValid());
@@ -1285,15 +1280,15 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
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.
+ // 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.
+ // 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();
@@ -1321,11 +1316,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
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.
+ // First, symplify things by looping through the symbol contexts to
+ // remove unwanted functions and separate out the functions we want to
+ // compare and prune into a separate list. Cache the info needed about
+ // the function declarations in a vector for efficiency.
SymbolContextList sc_sym_list;
uint32_t num_indices = sc_list.GetSize();
std::vector<FuncDeclInfo> fdi_cache;
@@ -1335,16 +1329,16 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
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.
+ // 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.
+ // 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))
@@ -1363,11 +1357,10 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
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.
+ // 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(
@@ -1536,9 +1529,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}
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.
+ // We couldn't find a non-symbol variable for this. Now we'll hunt for a
+ // generic data symbol, and -- if it is found -- treat it as a variable.
Status error;
const Symbol *data_symbol =
@@ -2116,7 +2108,8 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
parser_vars->m_llvm_value = NULL;
if (log) {
- ASTDumper ast_dumper(function_decl);
+ std::string function_str =
+ function_decl ? ASTDumper(function_decl).GetCString() : "nullptr";
StreamString ss;
@@ -2127,7 +2120,7 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
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());
+ ss.GetData(), function_str.c_str());
}
}
@@ -2165,7 +2158,7 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
CXXMethodDecl *method_decl =
ClangASTContext::GetASTContext(m_ast_context)
->AddMethodToCXXRecordType(
- copied_clang_type.GetOpaqueQualType(), "$__lldb_expr",
+ copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", NULL,
method_type, lldb::eAccessPublic, is_virtual, is_static,
is_inline, is_explicit, is_attr_used, is_artificial);
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index d163ad4f7e29..b67387930190 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -36,29 +36,28 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h
-/// "lldb/Expression/ClangExpressionDeclMap.h"
-/// @brief Manages named entities that are defined in LLDB's debug information.
+/// "lldb/Expression/ClangExpressionDeclMap.h" 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
+/// 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.
+/// 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.
+/// 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.
+/// 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:
@@ -169,8 +168,8 @@ public:
lldb::offset_t alignment);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Finalize the struct, laying out the position
- /// of each object in it.
+ /// [Used by IRForTarget] Finalize the struct, laying out the position of
+ /// each object in it.
///
/// @return
/// True on success; false otherwise.
@@ -178,8 +177,8 @@ public:
bool DoStructLayout();
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get general information about the laid-out
- /// struct after DoStructLayout() has been called.
+ /// [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.
@@ -197,8 +196,8 @@ public:
lldb::offset_t &alignment);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get specific information about one field
- /// of the laid-out struct after DoStructLayout() has been called.
+ /// [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
@@ -232,8 +231,7 @@ public:
uint32_t index);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get information about a function given its
- /// Decl.
+ /// [Used by IRForTarget] Get information about a function given its Decl.
///
/// @param[in] decl
/// The parsed Decl for the Function, as generated by ClangASTSource
@@ -248,8 +246,8 @@ public:
bool GetFunctionInfo(const clang::NamedDecl *decl, uint64_t &ptr);
//------------------------------------------------------------------
- /// [Used by IRForTarget] Get the address of a symbol given nothing
- /// but its name.
+ /// [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,
@@ -303,8 +301,8 @@ public:
TargetInfo GetTargetInfo();
//------------------------------------------------------------------
- /// [Used by ClangASTSource] Find all entities matching a given name,
- /// using a NameSearchContext to make Decls for them.
+ /// [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.
@@ -442,14 +440,13 @@ private:
void DisableStructVars() { m_struct_vars.reset(); }
//----------------------------------------------------------------------
- /// Get this parser's ID for use in extracting parser- and JIT-specific
- /// data from persistent variables.
+ /// 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 variable that matches the given name and
- /// type.
+ /// 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.
@@ -477,8 +474,8 @@ private:
TypeFromUser *type = NULL);
//------------------------------------------------------------------
- /// Get the value of a variable in a given execution context and return
- /// the associated Types if needed.
+ /// 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.
@@ -524,8 +521,8 @@ private:
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.
+ /// 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.
@@ -542,9 +539,8 @@ private:
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.
+ /// 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.
@@ -556,9 +552,9 @@ private:
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.
+ /// 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.
@@ -575,8 +571,7 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Use the NameSearchContext to generate a Decl for the given
- /// register.
+ /// Use the NameSearchContext to generate a Decl for the given register.
///
/// @param[in] context
/// The NameSearchContext to use when constructing the Decl.
@@ -588,8 +583,8 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Use the NameSearchContext to generate a Decl for the given
- /// type. (Types are not placed in the Tuple list.)
+ /// 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.
@@ -601,8 +596,8 @@ private:
unsigned int current_id);
//------------------------------------------------------------------
- /// Generate a Decl for "*this" and add a member function declaration
- /// to it for the expression, then report it.
+ /// 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.
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index d9e53074b3fb..c5406fcc3340 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -182,8 +182,7 @@ public:
m_manager->AddDiagnostic(new_diagnostic);
// Don't store away warning fixits, since the compiler doesn't have
- // enough
- // context in an expression for the warning to be useful.
+ // enough context in an expression for the warning to be useful.
// FIXME: Should we try to filter out FixIts that apply to our generated
// code, and not the user's expression?
if (severity == eDiagnosticSeverityError) {
@@ -226,10 +225,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_code_generator(), m_pp_callbacks(nullptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- // We can't compile expressions without a target. So if the exe_scope is null
- // or doesn't have a target,
- // then we just need to get out of here. I'll lldb_assert and not make any of
- // the compiler objects since
+ // We can't compile expressions without a target. So if the exe_scope is
+ // null or doesn't have a target, then we just need to get out of here. I'll
+ // lldb_assert and not make any of the compiler objects since
// I can't return errors directly from the constructor. Further calls will
// check if the compiler was made and
// bag out if it wasn't.
@@ -262,14 +260,14 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
const auto target_machine = target_arch.GetMachine();
- // If the expression is being evaluated in the context of an existing
- // stack frame, we introspect to see if the language runtime is available.
+ // If the expression is being evaluated in the context of an existing stack
+ // frame, we introspect to see if the language runtime is available.
lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame();
lldb::ProcessSP process_sp = exe_scope->CalculateProcess();
- // Make sure the user hasn't provided a preferred execution language
- // with `expression --language X -- ...`
+ // Make sure the user hasn't provided a preferred execution language with
+ // `expression --language X -- ...`
if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown)
frame_lang = frame_sp->GetLanguage();
@@ -281,8 +279,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
}
// 2. Configure the compiler with a set of default options that are
- // appropriate
- // for most situations.
+ // appropriate for most situations.
if (target_arch.IsValid()) {
std::string triple = target_arch.GetTriple().str();
m_compiler->getTargetOpts().Triple = triple;
@@ -292,19 +289,17 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
} else {
// If we get here we don't have a valid target and just have to guess.
// Sometimes this will be ok to just use the host target triple (when we
- // evaluate say "2+3", but other
- // expressions like breakpoint conditions and other things that _are_ target
- // specific really shouldn't just be
- // using the host triple. In such a case the language runtime should expose
- // an overridden options set (3),
- // below.
+ // evaluate say "2+3", but other expressions like breakpoint conditions and
+ // other things that _are_ target specific really shouldn't just be using
+ // the host triple. In such a case the language runtime should expose an
+ // overridden options set (3), below.
m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
if (log)
log->Printf("Using default target triple of %s",
m_compiler->getTargetOpts().Triple.c_str());
}
- // Now add some special fixes for known architectures:
- // Any arm32 iOS environment, but not on arm64
+ // Now add some special fixes for known architectures: Any arm32 iOS
+ // environment, but not on arm64
if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) {
@@ -317,8 +312,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_compiler->getTargetOpts().Features.push_back("+sse2");
}
- // Set the target CPU to generate code for.
- // This will be empty for any CPU that doesn't really need to make a special
+ // Set the target CPU to generate code for. This will be empty for any CPU
+ // that doesn't really need to make a special
// CPU string.
m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU();
@@ -328,11 +323,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_compiler->getTargetOpts().ABI = abi;
// 3. Now allow the runtime to provide custom configuration options for the
- // target.
- // In this case, a specialized language runtime is available and we can query
- // it for extra options.
- // For 99% of use cases, this will not be needed and should be provided when
- // basic platform detection is not enough.
+ // target. In this case, a specialized language runtime is available and we
+ // can query it for extra options. For 99% of use cases, this will not be
+ // needed and should be provided when basic platform detection is not enough.
if (lang_rt)
overridden_target_opts =
lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts());
@@ -378,9 +371,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
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.
+ // 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:
@@ -392,10 +385,10 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
// Clang now sets as default C++14 as the default standard (with
// GNU extensions), so we do the same here to avoid mismatches that
- // cause compiler error when evaluating expressions (e.g. nullptr
- // not found as it's a C++11 feature). Currently lldb evaluates
- // C++14 as C++11 (see two lines below) so we decide to be consistent
- // with that, but this could be re-evaluated in the future.
+ // cause compiler error when evaluating expressions (e.g. nullptr not found
+ // as it's a C++11 feature). Currently lldb evaluates C++14 as C++11 (see
+ // two lines below) so we decide to be consistent with that, but this could
+ // be re-evaluated in the future.
m_compiler->getLangOpts().CPlusPlus11 = true;
break;
case lldb::eLanguageTypeC_plus_plus:
@@ -407,8 +400,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
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.
+ // 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:
@@ -434,10 +427,9 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
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.
+ // 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;
if (process_sp && m_compiler->getLangOpts().ObjC1) {
@@ -513,8 +505,8 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
}
- // 8. Most of this we get from the CompilerInstance, but we
- // also want to give the context an ExternalASTSource.
+ // 8. Most of this we get from the CompilerInstance, but we also want to give
+ // the context an ExternalASTSource.
m_selector_table.reset(new SelectorTable());
m_builtin_context.reset(new Builtin::Context());
@@ -569,9 +561,7 @@ unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) {
codegenoptions::FullDebugInfo) {
int temp_fd = -1;
llvm::SmallString<PATH_MAX> result_path;
- FileSpec tmpdir_file_spec;
- if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir,
- tmpdir_file_spec)) {
+ if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
std::string temp_source_path = tmpdir_file_spec.GetPath();
llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
@@ -811,7 +801,7 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution(
{
auto lang = m_expr.Language();
if (log)
- log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__,
+ log->Printf("%s - Current expression language is %s\n", __FUNCTION__,
Language::GetNameForLanguageType(lang));
lldb::ProcessSP process_sp = exe_ctx.GetProcessSP();
if (process_sp && lang != lldb::eLanguageTypeUnknown) {
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
index 41f290f2e127..4058ec1270b3 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
@@ -26,14 +26,14 @@ class IRExecutionUnit;
//----------------------------------------------------------------------
/// @class ClangExpressionParser ClangExpressionParser.h
-/// "lldb/Expression/ClangExpressionParser.h"
-/// @brief Encapsulates an instance of Clang that can parse expressions.
+/// "lldb/Expression/ClangExpressionParser.h" 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.
+/// conversion to formats (DWARF bytecode, or JIT compiled machine code) that
+/// can be executed.
//----------------------------------------------------------------------
class ClangExpressionParser : public ExpressionParser {
public:
@@ -59,8 +59,8 @@ public:
~ClangExpressionParser() override;
//------------------------------------------------------------------
- /// Parse a single expression and convert it to IR using Clang. Don't
- /// wrap the expression in anything at all.
+ /// Parse a single expression and convert it to IR using Clang. Don't wrap
+ /// the expression in anything at all.
///
/// @param[in] diagnostic_manager
/// The diagnostic manager to report errors to.
@@ -74,8 +74,8 @@ public:
bool RewriteExpression(DiagnosticManager &diagnostic_manager) override;
//------------------------------------------------------------------
- /// Ready an already-parsed expression for execution, possibly
- /// evaluating it statically.
+ /// Ready an already-parsed expression for execution, possibly evaluating it
+ /// statically.
///
/// @param[out] func_addr
/// The address to which the function has been written.
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index baa80d7ba0d4..7d5ced5b4705 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -41,27 +41,25 @@ class ValueObjectConstResult;
//----------------------------------------------------------------------
/// @class ClangExpressionVariable ClangExpressionVariable.h
-/// "lldb/Expression/ClangExpressionVariable.h"
-/// @brief Encapsulates one variable for the expression parser.
+/// "lldb/Expression/ClangExpressionVariable.h" 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.
+/// 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.
+/// 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.
+/// 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.
+/// 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:
@@ -79,8 +77,8 @@ public:
lldb::ByteOrder byte_order, uint32_t addr_byte_size);
//----------------------------------------------------------------------
- /// Utility functions for dealing with ExpressionVariableLists in
- /// Clang-specific ways
+ /// Utility functions for dealing with ExpressionVariableLists in Clang-
+ /// specific ways
//----------------------------------------------------------------------
//----------------------------------------------------------------------
@@ -112,9 +110,9 @@ public:
}
//----------------------------------------------------------------------
- /// 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.
+ /// 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.
@@ -156,8 +154,8 @@ private:
public:
//----------------------------------------------------------------------
- /// Make this variable usable by the parser by allocating space for
- /// parser-specific variables
+ /// 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()));
diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
index a26ceda82d5f..e3e0ed49181e 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -101,14 +101,12 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
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.
+ // 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.
+ // the arguments list for the variable arguments.
uint32_t num_args = UINT32_MAX;
bool trust_function = false;
diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
index 0596d8fde7b9..438cf0c713da 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
@@ -31,8 +31,8 @@ class ClangExpressionParser;
//----------------------------------------------------------------------
/// @class ClangFunctionCaller ClangFunctionCaller.h
-/// "lldb/Expression/ClangFunctionCaller.h"
-/// @brief Encapsulates a function that can be called.
+/// "lldb/Expression/ClangFunctionCaller.h" 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
@@ -56,8 +56,8 @@ class ClangExpressionParser;
/// 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
+/// 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
@@ -79,8 +79,8 @@ class ClangFunctionCaller : public FunctionCaller {
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.
+ /// 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
diff --git a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp
new file mode 100644
index 000000000000..4251d2ee75b9
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp
@@ -0,0 +1,142 @@
+//===-- ClangHost.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangHost.h"
+
+#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Threading.h"
+
+// Project includes
+#include "lldb/Host/HostInfo.h"
+#if !defined(_WIN32)
+#include "lldb/Host/posix/HostInfoPosix.h"
+#endif
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Log.h"
+
+#include <string>
+
+using namespace lldb_private;
+
+#if defined(_WIN32)
+static bool ComputeClangDirectory(FileSpec &file_spec) { return false; }
+#else
+static bool DefaultComputeClangDirectory(FileSpec &file_spec) {
+ return HostInfoPosix::ComputePathRelativeToLibrary(
+ file_spec, (llvm::Twine("/lib") + CLANG_LIBDIR_SUFFIX + "/clang/" +
+ CLANG_VERSION_STRING)
+ .str());
+}
+
+#if defined(__APPLE__)
+
+static bool VerifyClangPath(const llvm::Twine &clang_path) {
+ if (llvm::sys::fs::is_directory(clang_path))
+ return true;
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (log)
+ log->Printf("VerifyClangPath(): "
+ "failed to stat clang resource directory at \"%s\"",
+ clang_path.str().c_str());
+ return false;
+}
+
+bool lldb_private::ComputeClangDirectory(FileSpec &lldb_shlib_spec,
+ FileSpec &file_spec, bool verify) {
+ std::string raw_path = lldb_shlib_spec.GetPath();
+
+ auto rev_it = llvm::sys::path::rbegin(raw_path);
+ auto r_end = llvm::sys::path::rend(raw_path);
+
+ // Check for a Posix-style build of LLDB.
+ while (rev_it != r_end) {
+ if (*rev_it == "LLDB.framework")
+ break;
+ ++rev_it;
+ }
+
+ if (rev_it == r_end)
+ return DefaultComputeClangDirectory(file_spec);
+
+ // Inside Xcode and in Xcode toolchains LLDB is always in lockstep
+ // with the Swift compiler, so it can reuse its Clang resource
+ // directory. This allows LLDB and the Swift compiler to share the
+ // same Clang module cache.
+ llvm::SmallString<256> clang_path;
+ const char *swift_clang_resource_dir = "usr/lib/swift/clang";
+ auto parent = std::next(rev_it);
+ if (parent != r_end && *parent == "SharedFrameworks") {
+ // This is the top-level LLDB in the Xcode.app bundle.
+ // E.g., "Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A"
+ raw_path.resize(parent - r_end);
+ llvm::sys::path::append(clang_path, raw_path,
+ "Developer/Toolchains/XcodeDefault.xctoolchain",
+ swift_clang_resource_dir);
+ if (!verify || VerifyClangPath(clang_path)) {
+ file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native);
+ return true;
+ }
+ } else if (parent != r_end && *parent == "PrivateFrameworks" &&
+ std::distance(parent, r_end) > 2) {
+ ++parent;
+ ++parent;
+ if (*parent == "System") {
+ // This is LLDB inside an Xcode toolchain.
+ // E.g., "Xcode.app/Contents/Developer/Toolchains/" \
+ // "My.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework"
+ raw_path.resize(parent - r_end);
+ llvm::sys::path::append(clang_path, raw_path, swift_clang_resource_dir);
+ if (!verify || VerifyClangPath(clang_path)) {
+ file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native);
+ return true;
+ }
+ raw_path = lldb_shlib_spec.GetPath();
+ }
+ raw_path.resize(rev_it - r_end);
+ } else {
+ raw_path.resize(rev_it - r_end);
+ }
+
+ // Fall back to the Clang resource directory inside the framework.
+ raw_path.append("LLDB.framework/Resources/Clang");
+ file_spec.SetFile(raw_path.c_str(), true, FileSpec::Style::native);
+ return true;
+}
+
+static bool ComputeClangDirectory(FileSpec &file_spec) {
+ if (FileSpec lldb_file_spec = HostInfo::GetShlibDir())
+ return ComputeClangDirectory(lldb_file_spec, file_spec, true);
+ return false;
+}
+#else // __APPLE__
+
+// All non-Apple posix systems.
+static bool ComputeClangDirectory(FileSpec &file_spec) {
+ return DefaultComputeClangDirectory(file_spec);
+}
+#endif // __APPLE__
+#endif // _WIN32
+
+FileSpec lldb_private::GetClangResourceDir() {
+ static FileSpec g_cached_resource_dir;
+ static llvm::once_flag g_once_flag;
+ llvm::call_once(g_once_flag, []() {
+ ::ComputeClangDirectory(g_cached_resource_dir);
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (log)
+ log->Printf("GetClangResourceDir() => '%s'",
+ g_cached_resource_dir.GetPath().c_str());
+ });
+ return g_cached_resource_dir;
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangHost.h b/source/Plugins/ExpressionParser/Clang/ClangHost.h
new file mode 100644
index 000000000000..4fe423adb1a5
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangHost.h
@@ -0,0 +1,26 @@
+//===-- ClangHost.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGHOST_H
+#define LLDB_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGHOST_H
+
+namespace lldb_private {
+
+class FileSpec;
+
+#if defined(__APPLE__)
+bool ComputeClangDirectory(FileSpec &lldb_shlib_spec, FileSpec &file_spec,
+ bool verify);
+#endif
+
+FileSpec GetClangResourceDir();
+
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index b42ceb9afee8..665195f01774 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -25,8 +25,10 @@
#include "llvm/Support/Threading.h"
// Project includes
+#include "ClangHost.h"
#include "ClangModulesDeclVendor.h"
+#include "lldb/Core/ModuleList.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -39,9 +41,9 @@
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.
+// 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();
@@ -61,8 +63,7 @@ private:
};
// The private implementation of our ClangModulesDeclVendor. Contains all the
-// Clang state required
-// to load modules.
+// Clang state required to load modules.
class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
public:
ClangModulesDeclVendorImpl(
@@ -144,18 +145,6 @@ void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
}
}
-static FileSpec GetResourceDir() {
- static FileSpec g_cached_resource_dir;
-
- static llvm::once_flag g_once_flag;
-
- llvm::call_once(g_once_flag, []() {
- HostInfo::GetLLDBPath(lldb::ePathTypeClangDir, g_cached_resource_dir);
- });
-
- return g_cached_resource_dir;
-}
-
ClangModulesDeclVendor::ClangModulesDeclVendor() {}
ClangModulesDeclVendor::~ClangModulesDeclVendor() {}
@@ -168,7 +157,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
: m_diagnostics_engine(std::move(diagnostics_engine)),
m_compiler_invocation(std::move(compiler_invocation)),
m_compiler_instance(std::move(compiler_instance)),
- m_parser(std::move(parser)) {}
+ m_parser(std::move(parser)), m_origin_map() {}
void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
std::set<ClangModulesDeclVendor::ModuleID> &exports,
@@ -590,14 +579,11 @@ ClangModulesDeclVendor::Create(Target &target) {
// 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");
+ llvm::SmallString<128> path;
+ auto props = ModuleList::GetGlobalModuleListProperties();
+ props.GetClangModulesCachePath().GetPath(path);
std::string module_cache_argument("-fmodules-cache-path=");
- module_cache_argument.append(DefaultModuleCache.str().str());
+ module_cache_argument.append(path.str());
compiler_invocation_arguments.push_back(module_cache_argument);
}
@@ -613,7 +599,7 @@ ClangModulesDeclVendor::Create(Target &target) {
}
{
- FileSpec clang_resource_dir = GetResourceDir();
+ FileSpec clang_resource_dir = GetClangResourceDir();
if (llvm::sys::fs::is_directory(clang_resource_dir.GetPath())) {
compiler_invocation_arguments.push_back("-resource-dir");
diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
index 8ebf78409a03..bb73d55a9a41 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -10,6 +10,7 @@
#include "ClangPersistentVariables.h"
#include "lldb/Core/Value.h"
+#include "lldb/Target/Target.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
@@ -52,14 +53,6 @@ void ClangPersistentVariables::RemovePersistentVariable(
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::RegisterPersistentDecl(const ConstString &name,
clang::NamedDecl *decl) {
m_persistent_decls.insert(
diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index 16981a7fe14a..59126974616d 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -25,9 +25,8 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangPersistentVariables ClangPersistentVariables.h
-/// "lldb/Expression/ClangPersistentVariables.h"
-/// @brief Manages persistent values that need to be preserved between
-/// expression invocations.
+/// "lldb/Expression/ClangPersistentVariables.h" 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,
@@ -54,16 +53,11 @@ public:
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;
+ llvm::StringRef
+ GetPersistentVariablePrefix(bool is_error) const override {
+ return "$";
+ }
void RegisterPersistentDecl(const ConstString &name, clang::NamedDecl *decl);
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 18fe8b49227b..2e61f704127a 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -65,7 +65,8 @@ ClangUserExpression::ClangUserExpression(
options),
m_type_system_helper(*m_target_wp.lock().get(),
options.GetExecutionPolicy() ==
- eExecutionPolicyTopLevel) {
+ eExecutionPolicyTopLevel),
+ m_result_delegate(exe_scope.CalculateTarget()) {
switch (m_language) {
case lldb::eLanguageTypeC_plus_plus:
m_allow_cxx = true;
@@ -195,12 +196,10 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
} 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.
+ // 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);
@@ -290,10 +289,10 @@ void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Status &err) {
}
}
-// 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.
+// 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)["
@@ -308,17 +307,23 @@ static void ApplyObjcCastHack(std::string &expr) {
#undef OBJC_CAST_HACK_FROM
}
-bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
- ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory,
- bool generate_debug_info) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+namespace {
+// Utility guard that calls a callback when going out of scope.
+class OnExit {
+public:
+ typedef std::function<void(void)> Callback;
- Status err;
+ OnExit(Callback const &callback) : m_callback(callback) {}
- InstallContext(exe_ctx);
+ ~OnExit() { m_callback(); }
+
+private:
+ Callback m_callback;
+};
+} // namespace
+bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx) {
if (Target *target = exe_ctx.GetTargetPtr()) {
if (PersistentExpressionState *persistent_state =
target->GetPersistentExpressionStateForLanguage(
@@ -335,26 +340,15 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
"error: couldn't start parsing (no target)");
return false;
}
+ return true;
+}
- ScanContext(exe_ctx, err);
-
- if (!err.Success()) {
- diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString());
- }
-
- ////////////////////////////////////
- // Generate the expression
- //
-
- ApplyObjcCastHack(m_expr_text);
-
- std::string prefix = m_expr_prefix;
-
+static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
if (ClangModulesDeclVendor *decl_vendor =
- m_target->GetClangModulesDeclVendor()) {
+ target->GetClangModulesDeclVendor()) {
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
llvm::cast<ClangPersistentVariables>(
- m_target->GetPersistentExpressionStateForLanguage(
+ target->GetPersistentExpressionStateForLanguage(
lldb::eLanguageTypeC))
->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
@@ -363,7 +357,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
modules_for_macros.push_back(module);
}
- if (m_target->GetEnableAutoImportClangModules()) {
+ if (target->GetEnableAutoImportClangModules()) {
if (StackFrame *frame = exe_ctx.GetFramePtr()) {
if (Block *block = frame->GetFrameBlock()) {
SymbolContext sc;
@@ -380,8 +374,13 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
}
}
}
+}
- lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown;
+llvm::Optional<lldb::LanguageType> ClangUserExpression::GetLanguageForExpr(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
+ lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown;
+
+ std::string prefix = m_expr_prefix;
if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
m_transformed_text = m_expr_text;
@@ -401,9 +400,50 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
exe_ctx)) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"couldn't construct expression body");
- return false;
+ return llvm::Optional<lldb::LanguageType>();
}
}
+ return lang_type;
+}
+
+bool ClangUserExpression::PrepareForParsing(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
+ InstallContext(exe_ctx);
+
+ if (!SetupPersistentState(diagnostic_manager, exe_ctx))
+ return false;
+
+ Status err;
+ ScanContext(exe_ctx, err);
+
+ if (!err.Success()) {
+ diagnostic_manager.PutString(eDiagnosticSeverityWarning, err.AsCString());
+ }
+
+ ////////////////////////////////////
+ // Generate the expression
+ //
+
+ ApplyObjcCastHack(m_expr_text);
+
+ SetupDeclVendor(exe_ctx, m_target);
+ return true;
+}
+
+bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory,
+ bool generate_debug_info) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!PrepareForParsing(diagnostic_manager, exe_ctx))
+ return false;
+
+ lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown;
+ if (auto new_lang = GetLanguageForExpr(diagnostic_manager, exe_ctx)) {
+ lang_type = new_lang.getValue();
+ }
if (log)
log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
@@ -427,28 +467,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
- class OnExit {
- public:
- typedef std::function<void(void)> Callback;
-
- OnExit(Callback const &callback) : m_callback(callback) {}
-
- ~OnExit() { m_callback(); }
-
- private:
- Callback m_callback;
- };
-
OnExit on_exit([this]() { ResetDeclMap(); });
if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
-
- ResetDeclMap(); // We are being careful here in the case of breakpoint
- // conditions.
-
return false;
}
@@ -463,17 +487,15 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
exe_scope = exe_ctx.GetTargetPtr();
// We use a shared pointer here so we can use the original parser - if it
- // succeeds
- // or the rewrite parser we might make if it fails. But the parser_sp will
- // never be empty.
+ // succeeds or the rewrite parser we might make if it fails. But the
+ // parser_sp will never be empty.
ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
unsigned num_errors = parser.Parse(diagnostic_manager);
// Check here for FixItHints. If there are any try to apply the fixits and
- // set the fixed text in m_fixed_text
- // before returning an error.
+ // set the fixed text in m_fixed_text before returning an error.
if (num_errors) {
if (diagnostic_manager.HasFixIts()) {
if (parser.RewriteExpression(diagnostic_manager)) {
@@ -487,16 +509,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
fixed_expression.substr(fixed_start, fixed_end - fixed_start);
}
}
-
- 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
+ // Prepare the output of the parser for execution, evaluating it statically
+ // if possible
//
{
@@ -539,9 +557,9 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
register_execution_unit = true;
}
- // If there is more than one external function in the execution
- // unit, it needs to keep living even if it's not top level, because
- // the result could refer to that function.
+ // If there is more than one external function in the execution unit, it
+ // needs to keep living even if it's not top level, because the result
+ // could refer to that function.
if (m_execution_unit_sp->GetJittedFunctions().size() > 1) {
register_execution_unit = true;
@@ -568,10 +586,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
}
}
- 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 (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
return true;
@@ -667,10 +681,10 @@ void ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() {
}
}
-ClangUserExpression::ResultDelegate::ResultDelegate() {}
-
ConstString ClangUserExpression::ResultDelegate::GetName() {
- return m_persistent_state->GetNextPersistentVariableName();
+ auto prefix = m_persistent_state->GetPersistentVariablePrefix();
+ return m_persistent_state->GetNextPersistentVariableName(*m_target_sp,
+ prefix);
}
void ClangUserExpression::ResultDelegate::DidDematerialize(
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index 88a78798b657..ac363bf91747 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -35,13 +35,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangUserExpression ClangUserExpression.h
-/// "lldb/Expression/ClangUserExpression.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// "lldb/Expression/ClangUserExpression.h" 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.
+/// 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:
@@ -69,8 +69,8 @@ public:
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.
+ /// 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
@@ -174,11 +174,18 @@ private:
lldb::addr_t struct_address,
DiagnosticManager &diagnostic_manager) override;
+ llvm::Optional<lldb::LanguageType> GetLanguageForExpr(
+ DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx);
+ bool SetupPersistentState(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx);
+ bool PrepareForParsing(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx);
+
ClangUserExpressionHelper m_type_system_helper;
class ResultDelegate : public Materializer::PersistentVariableDelegate {
public:
- ResultDelegate();
+ ResultDelegate(lldb::TargetSP target) : m_target_sp(target) {}
ConstString GetName() override;
void DidDematerialize(lldb::ExpressionVariableSP &variable) override;
@@ -188,6 +195,7 @@ private:
private:
PersistentExpressionState *m_persistent_state;
lldb::ExpressionVariableSP m_variable;
+ lldb::TargetSP m_target_sp;
};
ResultDelegate m_result_delegate;
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index 80577199b818..a897a2b17087 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -29,15 +29,15 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class ClangUtilityFunction ClangUtilityFunction.h
-/// "lldb/Expression/ClangUtilityFunction.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// "lldb/Expression/ClangUtilityFunction.h" 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.
+/// simply provide a way to push a function into the target for the debugger
+/// to call later on.
//----------------------------------------------------------------------
class ClangUtilityFunction : public UtilityFunction {
public:
@@ -60,8 +60,8 @@ public:
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.
+ /// 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
diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index 13f5657eedd8..e51c9ee07b9f 100644
--- a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -263,8 +263,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
}
// Get the next available result name from m_decl_map and create the
- // persistent
- // variable for it
+ // persistent variable for it
// If the result is an Lvalue, it is emitted as a pointer; see
// ASTResultSynthesizer::SynthesizeBodyResult.
@@ -345,9 +344,9 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
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
+ // 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.
@@ -464,9 +463,7 @@ bool IRForTarget::RewriteObjCConstString(llvm::GlobalVariable *ns_str,
// 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
+ // pointer size for now) CFStringEncoding -> i32 Boolean -> i8
Type *arg_type_array[5];
@@ -801,9 +798,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
// Unpack the message name from the selector. In LLVM IR, an objc_msgSend
// gets represented as
//
- // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*>
- // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...)
- // ; <i8*>
+ // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*> %call = call
+ // i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
//
// where %obj is the object pointer and %tmp is the selector.
//
@@ -870,7 +866,8 @@ bool IRForTarget::RewriteObjCSelector(Instruction *selector_load) {
log->Printf("Found sel_registerName at 0x%" PRIx64,
sel_registerName_addr);
- // Build the function type: struct objc_selector *sel_registerName(uint8_t*)
+ // 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*
@@ -980,11 +977,10 @@ bool IRForTarget::RewriteObjCClassReference(Instruction *class_load) {
// %struct._objc_class** @OBJC_CLASS_REFERENCES_, align 4
//
// @"OBJC_CLASS_REFERENCES_ is a bitcast of a character array called
- // @OBJC_CLASS_NAME_.
- // @OBJC_CLASS_NAME contains the string.
+ // @OBJC_CLASS_NAME_. @OBJC_CLASS_NAME contains the string.
- // Find the pointer's initializer (a ConstantExpr with opcode BitCast)
- // and get the string from its target
+ // Find the pointer's initializer (a ConstantExpr with opcode BitCast) and
+ // get the string from its target
GlobalVariable *_objc_class_references_ =
dyn_cast<GlobalVariable>(load->getPointerOperand());
@@ -1159,8 +1155,8 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {
GlobalValue::ExternalLinkage, NULL, /* no initializer */
alloc->getName().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.
+ // 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");
@@ -1175,8 +1171,7 @@ bool IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc) {
named_metadata->addOperand(persistent_global_md);
// Now, since the variable is a pointer variable, we will drop in a load of
- // that
- // pointer variable.
+ // that pointer variable.
LoadInst *persistent_load = new LoadInst(persistent_global, "", alloc);
@@ -1366,16 +1361,13 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {
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.
+ // 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.
+ // 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();
@@ -1965,12 +1957,11 @@ bool IRForTarget::ReplaceVariables(Function &llvm_function) {
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.
+ // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
+ // in cases where the result variable is an rvalue, we have to
+ // synthesize a dereference of the appropriate structure entry in
+ // order to produce the static variable that the AST thinks it is
+ // accessing.
llvm::Instruction *entry_instruction = llvm::cast<Instruction>(
m_entry_instruction_finder.GetValue(function));
@@ -2194,7 +2185,8 @@ bool IRForTarget::runOnModule(Module &llvm_module) {
if (log)
log->Printf("RewriteObjCSelectors() failed");
- // RewriteObjCSelectors() reports its own errors, so we don't do so here
+ // RewriteObjCSelectors() reports its own errors, so we don't do so
+ // here
return false;
}
diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h
index 93ce8aa44eb2..c6c44b46023c 100644
--- a/source/Plugins/ExpressionParser/Clang/IRForTarget.h
+++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -47,12 +47,11 @@ class IRMemoryMap;
//----------------------------------------------------------------------
/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h"
-/// @brief Transforms the IR for a function to run in the target
+/// 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.
+/// 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
@@ -126,8 +125,7 @@ public:
//------------------------------------------------------------------
/// Interface stub
///
- /// Implementation of the llvm::ModulePass::assignPassManager()
- /// function.
+ /// Implementation of the llvm::ModulePass::assignPassManager() function.
//------------------------------------------------------------------
void assignPassManager(llvm::PMStack &pass_mgr_stack,
llvm::PassManagerType pass_mgr_type =
@@ -179,8 +177,8 @@ private:
//------------------------------------------------------------------
//------------------------------------------------------------------
- /// Get the address of a function, and a location to put the complete
- /// Value of the function if one is available.
+ /// 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.
@@ -204,13 +202,13 @@ private:
//------------------------------------------------------------------
/// A function-level pass to take the generated global value
- /// $__lldb_expr_result and make it into a persistent variable.
- /// Also see ASTResultSynthesizer.
+ /// $__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.
+ /// Find the NamedDecl corresponding to a Value. This interface is exposed
+ /// for the IR interpreter.
///
/// @param[in] module
/// The module containing metadata to search
@@ -230,8 +228,8 @@ private:
//------------------------------------------------------------------
/// 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.
+ /// 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.
@@ -247,8 +245,8 @@ private:
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
+ /// 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
@@ -301,10 +299,9 @@ private:
/// 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.
+ /// 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.
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -359,13 +356,12 @@ private:
//------------------------------------------------------------------
/// 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().
+ /// 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().
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -389,15 +385,14 @@ private:
//------------------------------------------------------------------
/// 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.
+ /// 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.
+ /// Write an initializer to a memory array of assumed sufficient size.
///
/// @param[in] data
/// A pointer to the data to write to.
@@ -504,8 +499,8 @@ private:
//------------------------------------------------------------------
/// 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.
+ /// variable. Static variables normally have guard variables to ensure that
+ /// they are only initialized once.
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -529,9 +524,9 @@ private:
//------------------------------------------------------------------
/// 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.
+ /// point at the correct offsets from the void* passed into the function.
+ /// ClangExpressionDeclMap::DoStructLayout() must be called beforehand, so
+ /// that the offsets are valid.
//------------------------------------------------------------------
//------------------------------------------------------------------
@@ -583,7 +578,8 @@ private:
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.
+ /// 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)
@@ -594,18 +590,17 @@ private:
/// 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 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.
+ /// 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.
@@ -637,8 +632,8 @@ private:
lldb_private::Stream &error_stream);
//------------------------------------------------------------------
- /// Construct a reference to m_reloc_placeholder with a given type
- /// and offset. This typically happens after inserting data into
+ /// 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
@@ -653,8 +648,8 @@ private:
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.
+ /// 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
diff --git a/source/Plugins/ExpressionParser/Go/GoParser.cpp b/source/Plugins/ExpressionParser/Go/GoParser.cpp
index 538bd05e25f8..9c845d02bca0 100644
--- a/source/Plugins/ExpressionParser/Go/GoParser.cpp
+++ b/source/Plugins/ExpressionParser/Go/GoParser.cpp
@@ -67,7 +67,9 @@ private:
size_t m_pos;
};
-GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false) {}
+GoParser::GoParser(const char *src)
+ : m_lexer(src), m_pos(0), m_last_tok(GoLexer::TOK_INVALID),
+ m_failed(false) {}
GoASTStmt *GoParser::Statement() {
Rule r("Statement", this);
@@ -437,8 +439,10 @@ GoASTExpr *GoParser::CompositeLit() {
if (!type)
return r.error();
GoASTCompositeLit *lit = LiteralValue();
- if (!lit)
+ if (!lit) {
+ delete type;
return r.error();
+ }
lit->SetType(type);
return lit;
}
@@ -546,6 +550,7 @@ GoASTExpr *GoParser::Arguments(GoASTExpr *e) {
GoASTExpr *GoParser::Conversion() {
Rule r("Conversion", this);
if (GoASTExpr *t = Type2()) {
+ std::unique_ptr<GoASTExpr> owner(t);
if (match(GoLexer::OP_LPAREN)) {
GoASTExpr *v = Expression();
if (!v)
@@ -555,6 +560,7 @@ GoASTExpr *GoParser::Conversion() {
return r.error();
GoASTCallExpr *call = new GoASTCallExpr(false);
call->SetFun(t);
+ owner.release();
call->AddArgs(v);
return call;
}
diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
index f4b8cfbe03d4..3a10a1dc767a 100644
--- a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
+++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
@@ -171,12 +171,11 @@ private:
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);
+ const uint32_t match_count =
+ target->GetImages().FindGlobalVariables(fullname, 1, variable_list);
if (match_count == 1) {
return variable_list.GetVariableAtIndex(0);
}
@@ -272,7 +271,8 @@ GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
PersistentExpressionState *pv =
target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
if (pv != nullptr) {
- result->SetName(pv->GetNextPersistentVariableName());
+ result->SetName(pv->GetNextPersistentVariableName(
+ *target, pv->GetPersistentVariablePrefix()));
pv->AddVariable(result);
}
return lldb::eExpressionCompleted;
@@ -400,8 +400,7 @@ ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) {
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'.
+ // 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);
@@ -651,15 +650,6 @@ ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr(
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);
diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/source/Plugins/ExpressionParser/Go/GoUserExpression.h
index 03ceb76b8431..e2839da9bfdd 100644
--- a/source/Plugins/ExpressionParser/Go/GoUserExpression.h
+++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.h
@@ -29,8 +29,10 @@ class GoPersistentExpressionState : public PersistentExpressionState {
public:
GoPersistentExpressionState();
- ConstString GetNextPersistentVariableName() override;
-
+ llvm::StringRef
+ GetPersistentVariablePrefix(bool is_error) const override {
+ return "$go";
+ }
void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
lldb::addr_t LookupSymbol(const ConstString &name) override {
@@ -48,12 +50,12 @@ private:
//----------------------------------------------------------------------
/// @class GoUserExpression GoUserExpression.h
-/// "lldb/Expression/GoUserExpression.h"
-/// @brief Encapsulates a single expression for use with Go
+/// "lldb/Expression/GoUserExpression.h" 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.
+/// and as a backend for the expr command. GoUserExpression encapsulates the
+/// objects needed to parse and interpret an expression.
//----------------------------------------------------------------------
class GoUserExpression : public UserExpression {
public:
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 262a7914d249..86744520ad63 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -258,8 +258,8 @@ static bool GetARMDWARFRegisterInfo(unsigned reg_num, RegisterInfo &reg_info) {
reg_info.name = "f7";
break;
- // Intel wireless MMX general purpose registers 0 - 7
- // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7)
+ // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
+ // register 0 - 7 (they do overlap with wCGR0 - wCGR7)
case dwarf_wCGR0:
reg_info.name = "wCGR0/ACC0";
break;
@@ -901,7 +901,8 @@ uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
}
// Push Multiple Registers stores multiple registers to the stack, storing to
-// consecutive memory locations ending just below the address in SP, and updates
+// consecutive memory locations ending just below the address in SP, and
+// updates
// SP to point to the start of the stored data.
bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -1390,8 +1391,8 @@ bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
uint32_t imm32; // the immediate value to be written to Rd
uint32_t carry =
0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
- // for setflags == false, this value is a don't care
- // initialized to 0 to silence the static analyzer
+ // for setflags == false, this value is a don't care initialized to
+ // 0 to silence the static analyzer
bool setflags;
switch (encoding) {
case eEncodingT1:
@@ -1473,12 +1474,11 @@ bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
// MUL multiplies two register values. The least significant 32 bits of the
// result are written to the destination
// register. These 32 bits do not depend on whether the source register values
-// are considered to be signed values or
-// unsigned values.
+// are considered to be signed values or unsigned values.
//
// Optionally, it can update the condition flags based on the result. In the
-// Thumb instruction set, this option is
-// limited to only a few forms of the instruction.
+// Thumb instruction set, this option is limited to only a few forms of the
+// instruction.
bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -1606,8 +1606,8 @@ bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
}
// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
-// the destination register.
-// It can optionally update the condition flags based on the value.
+// the destination register. It can optionally update the condition flags based
+// on the value.
bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -1666,8 +1666,8 @@ bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
}
// Bitwise NOT (register) writes the bitwise inverse of a register value to the
-// destination register.
-// It can optionally update the condition flags based on the result.
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2005,9 +2005,9 @@ bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
return true;
}
-// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
-// at a PC-relative address, and changes instruction set from ARM to Thumb, or
-// from Thumb to ARM.
+// Branch with Link and Exchange Instruction Sets (immediate) calls a
+// subroutine at a PC-relative address, and changes instruction set from ARM to
+// Thumb, or from Thumb to ARM.
// BLX (immediate)
bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -2110,8 +2110,8 @@ bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
return true;
}
-// Branch with Link and Exchange (register) calls a subroutine at an address and
-// instruction set specified by a register.
+// Branch with Link and Exchange (register) calls a subroutine at an address
+// and instruction set specified by a register.
// BLX (register)
bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -2220,9 +2220,8 @@ bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
}
// Branch and Exchange Jazelle attempts to change to Jazelle state. If the
-// attempt fails, it branches to an
-// address and instruction set specified by a register as though it were a BX
-// instruction.
+// attempt fails, it branches to an address and instruction set specified by a
+// register as though it were a BX instruction.
//
// TODO: Emulate Jazelle architecture?
// We currently assume that switching to Jazelle state fails, thus
@@ -2561,8 +2560,8 @@ bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
return true;
}
-// Vector Push stores multiple extension registers to the stack.
-// It also updates SP to point to the start of the stored data.
+// Vector Push stores multiple extension registers to the stack. It also
+// updates SP to point to the start of the stored data.
bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2577,7 +2576,8 @@ bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
MemA[address,4] = S[d+r]; address = address+4;
else
for r = 0 to regs-1
- // Store as two word-aligned words in the correct order for current endianness.
+ // Store as two word-aligned words in the correct order for
+ // current endianness.
MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
address = address+8;
@@ -2653,8 +2653,8 @@ bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
return true;
}
-// Vector Pop loads multiple extension registers from the stack.
-// It also updates SP to point just above the loaded data.
+// Vector Pop loads multiple extension registers from the stack. It also
+// updates SP to point just above the loaded data.
bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2670,7 +2670,8 @@ bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
else
for r = 0 to regs-1
word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
- // Combine the word-aligned words in the correct order for current endianness.
+ // Combine the word-aligned words in the correct order for
+ // current endianness.
D[d+r] = if BigEndian() then word1:word2 else word2:word1;
}
#endif
@@ -2892,10 +2893,8 @@ bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
}
// Compare and Branch on Nonzero and Compare and Branch on Zero compare the
-// value in a register with
-// zero and conditionally branch forward a constant value. They do not affect
-// the condition flags.
-// CBNZ, CBZ
+// value in a register with zero and conditionally branch forward a constant
+// value. They do not affect the condition flags. CBNZ, CBZ
bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2938,8 +2937,8 @@ bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
return true;
}
-// Table Branch Byte causes a PC-relative forward branch using a table of single
-// byte offsets.
+// Table Branch Byte causes a PC-relative forward branch using a table of
+// single byte offsets.
// A base register provides a pointer to the table, and a second register
// supplies an index into the table.
// The branch length is twice the value of the byte returned from the table.
@@ -2948,8 +2947,8 @@ bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
// single halfword offsets.
// A base register provides a pointer to the table, and a second register
// supplies an index into the table.
-// The branch length is twice the value of the halfword returned from the table.
-// TBB, TBH
+// The branch length is twice the value of the halfword returned from the
+// table. TBB, TBH
bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -2984,9 +2983,8 @@ bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
return false;
}
- // Read the address of the table from the operand register Rn.
- // The PC can be used, in which case the table immediately follows this
- // instruction.
+ // Read the address of the table from the operand register Rn. The PC can
+ // be used, in which case the table immediately follows this instruction.
uint32_t base = ReadCoreReg(Rn, &success);
if (!success)
return false;
@@ -3023,8 +3021,8 @@ bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
}
// This instruction adds an immediate value to a register value, and writes the
-// result to the destination register.
-// It can optionally update the condition flags based on the result.
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3145,8 +3143,8 @@ bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
}
// This instruction adds an immediate value to a register value, and writes the
-// result to the destination
-// register. It can optionally update the condition flags based on the result.
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3210,9 +3208,8 @@ bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
}
// This instruction adds a register value and an optionally-shifted register
-// value, and writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// value, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3350,8 +3347,8 @@ bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
}
// Compare Negative (register) adds a register value and an optionally-shifted
-// register value.
-// It updates the condition flags based on the result, and discards the result.
+// register value. It updates the condition flags based on the result, and
+// discards the result.
bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3419,8 +3416,8 @@ bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
return true;
}
-// Compare (immediate) subtracts an immediate value from a register value.
-// It updates the condition flags based on the result, and discards the result.
+// Compare (immediate) subtracts an immediate value from a register value. It
+// updates the condition flags based on the result, and discards the result.
bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3473,8 +3470,8 @@ bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
}
// Compare (register) subtracts an optionally-shifted register value from a
-// register value.
-// It updates the condition flags based on the result, and discards the result.
+// register value. It updates the condition flags based on the result, and
+// discards the result.
bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3552,10 +3549,9 @@ bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
}
// Arithmetic Shift Right (immediate) shifts a register value right by an
-// immediate number of bits,
-// shifting in copies of its sign bit, and writes the result to the destination
-// register. It can
-// optionally update the condition flags based on the result.
+// immediate number of bits, shifting in copies of its sign bit, and writes the
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3577,13 +3573,11 @@ bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
return EmulateShiftImm(opcode, encoding, SRType_ASR);
}
-// Arithmetic Shift Right (register) shifts a register value right by a variable
-// number of bits,
-// shifting in copies of its sign bit, and writes the result to the destination
-// register.
-// The variable number of bits is read from the bottom byte of a register. It
-// can optionally update
-// the condition flags based on the result.
+// Arithmetic Shift Right (register) shifts a register value right by a
+// variable number of bits, shifting in copies of its sign bit, and writes the
+// result to the destination register. The variable number of bits is read from
+// the bottom byte of a register. It can optionally update the condition flags
+// based on the result.
bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3604,10 +3598,8 @@ bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
}
// Logical Shift Left (immediate) shifts a register value left by an immediate
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. It can
-// optionally
-// update the condition flags based on the result.
+// number of bits, shifting in zeros, and writes the result to the destination
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3630,12 +3622,9 @@ bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
}
// Logical Shift Left (register) shifts a register value left by a variable
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. The
-// variable number
-// of bits is read from the bottom byte of a register. It can optionally update
-// the condition
-// flags based on the result.
+// number of bits, shifting in zeros, and writes the result to the destination
+// register. The variable number of bits is read from the bottom byte of a
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3655,11 +3644,10 @@ bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
return EmulateShiftReg(opcode, encoding, SRType_LSL);
}
-// Logical Shift Right (immediate) shifts a register value right by an immediate
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. It can
-// optionally
-// update the condition flags based on the result.
+// Logical Shift Right (immediate) shifts a register value right by an
+// immediate number of bits, shifting in zeros, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3682,12 +3670,9 @@ bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
}
// Logical Shift Right (register) shifts a register value right by a variable
-// number of bits,
-// shifting in zeros, and writes the result to the destination register. The
-// variable number
-// of bits is read from the bottom byte of a register. It can optionally update
-// the condition
-// flags based on the result.
+// number of bits, shifting in zeros, and writes the result to the destination
+// register. The variable number of bits is read from the bottom byte of a
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3708,10 +3693,9 @@ bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
}
// Rotate Right (immediate) provides the value of the contents of a register
-// rotated by a constant value.
-// The bits that are rotated off the right end are inserted into the vacated bit
-// positions on the left.
-// It can optionally update the condition flags based on the result.
+// rotated by a constant value. The bits that are rotated off the right end are
+// inserted into the vacated bit positions on the left. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3734,12 +3718,10 @@ bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
}
// Rotate Right (register) provides the value of the contents of a register
-// rotated by a variable number of bits.
-// The bits that are rotated off the right end are inserted into the vacated bit
-// positions on the left.
-// The variable number of bits is read from the bottom byte of a register. It
-// can optionally update the condition
-// flags based on the result.
+// rotated by a variable number of bits. The bits that are rotated off the
+// right end are inserted into the vacated bit positions on the left. The
+// variable number of bits is read from the bottom byte of a register. It can
+// optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -3760,8 +3742,7 @@ bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
}
// Rotate Right with Extend provides the value of the contents of a register
-// shifted right by one place,
-// with the carry flag shifted into bit [31].
+// shifted right by one place, with the carry flag shifted into bit [31].
//
// RRX can optionally update the condition flags based on the result.
// In that case, bit [0] is shifted into the carry flag.
@@ -3808,10 +3789,9 @@ bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
// A8.6.139 ROR (immediate) -- Encoding T1
ARMEncoding use_encoding = encoding;
if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
- // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding
- // to
- // have the same decoding of bit fields as the other Thumb2 shift
- // operations.
+ // Morph the T1 encoding from the ARM Architecture Manual into T2
+ // encoding to have the same decoding of bit fields as the other Thumb2
+ // shift operations.
use_encoding = eEncodingT2;
}
@@ -3950,8 +3930,7 @@ bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
// LDM loads multiple registers from consecutive memory locations, using an
// address from a base register. Optionally the address just above the highest
-// of those locations
-// can be written back to the base register.
+// of those locations can be written back to the base register.
bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4093,8 +4072,8 @@ bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
// LDMDA loads multiple registers from consecutive memory locations using an
// address from a base register.
// The consecutive memory locations end at this address and the address just
-// below the lowest of those locations
-// can optionally be written back to the base register.
+// below the lowest of those locations can optionally be written back to the
+// base register.
bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4210,8 +4189,8 @@ bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
// LDMDB loads multiple registers from consecutive memory locations using an
// address from a base register. The
// consecutive memory locations end just below this address, and the address of
-// the lowest of those locations can
-// be optionally written back to the base register.
+// the lowest of those locations can be optionally written back to the base
+// register.
bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4349,8 +4328,8 @@ bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
// LDMIB loads multiple registers from consecutive memory locations using an
// address from a base register. The
// consecutive memory locations start just above this address, and thea ddress
-// of the last of those locations can
-// optinoally be written back to the base register.
+// of the last of those locations can optinoally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4461,8 +4440,7 @@ bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
}
// Load Register (immediate) calculates an address from a base register value
-// and
-// an immediate offset, loads a word from memory, and writes to a register.
+// and an immediate offset, loads a word from memory, and writes to a register.
// LDR (immediate, Thumb)
bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -4625,8 +4603,8 @@ bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
// STM (Store Multiple Increment After) stores multiple registers to consecutive
// memory locations using an address
// from a base register. The consecutive memory locations start at this
-// address, and the address just above the last
-// of those locations can optionally be written back to the base register.
+// address, and the address just above the last of those locations can
+// optionally be written back to the base register.
bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4775,10 +4753,10 @@ bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
}
// STMDA (Store Multiple Decrement After) stores multiple registers to
-// consecutive memory locations using an address
-// from a base register. The consecutive memory locations end at this address,
-// and the address just below the lowest
-// of those locations can optionally be written back to the base register.
+// consecutive memory locations using an address from a base register. The
+// consecutive memory locations end at this address, and the address just below
+// the lowest of those locations can optionally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -4897,10 +4875,10 @@ bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
}
// STMDB (Store Multiple Decrement Before) stores multiple registers to
-// consecutive memory locations using an address
-// from a base register. The consecutive memory locations end just below this
-// address, and the address of the first of
-// those locations can optionally be written back to the base register.
+// consecutive memory locations using an address from a base register. The
+// consecutive memory locations end just below this address, and the address of
+// the first of those locations can optionally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5046,10 +5024,10 @@ bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
}
// STMIB (Store Multiple Increment Before) stores multiple registers to
-// consecutive memory locations using an address
-// from a base register. The consecutive memory locations start just above this
-// address, and the address of the last
-// of those locations can optionally be written back to the base register.
+// consecutive memory locations using an address from a base register. The
+// consecutive memory locations start just above this address, and the address
+// of the last of those locations can optionally be written back to the base
+// register.
bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5337,8 +5315,8 @@ bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
// STR (Store Register) calculates an address from a base register value and an
// offset register value, stores a
-// word from a register to memory. The offset register value can optionally be
-// shifted.
+// word from a register to memory. The offset register value can optionally
+// be shifted.
bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5423,7 +5401,7 @@ bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -5664,8 +5642,8 @@ bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
// STRH (register) calculates an address from a base register value and an
// offset register value, and stores a
-// halfword from a register to memory. The offset register value can be shifted
-// left by 0, 1, 2, or 3 bits.
+// halfword from a register to memory. The offset register value can be
+// shifted left by 0, 1, 2, or 3 bits.
bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5745,7 +5723,7 @@ bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -5842,10 +5820,8 @@ bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
}
// Add with Carry (immediate) adds an immediate value and the carry flag value
-// to a register value,
-// and writes the result to the destination register. It can optionally update
-// the condition flags
-// based on the result.
+// to a register value, and writes the result to the destination register. It
+// can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5911,11 +5887,10 @@ bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
return true;
}
-// Add with Carry (register) adds a register value, the carry flag value, and an
-// optionally-shifted
-// register value, and writes the result to the destination register. It can
-// optionally update the
-// condition flags based on the result.
+// Add with Carry (register) adds a register value, the carry flag value, and
+// an optionally-shifted register value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -5999,9 +5974,8 @@ bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
return true;
}
-// This instruction adds an immediate value to the PC value to form a
-// PC-relative address,
-// and writes the result to the destination register.
+// This instruction adds an immediate value to the PC value to form a PC-
+// relative address, and writes the result to the destination register.
bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6063,9 +6037,8 @@ bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
}
// This instruction performs a bitwise AND of a register value and an immediate
-// value, and writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// value, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6139,10 +6112,8 @@ bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
}
// This instruction performs a bitwise AND of a register value and an
-// optionally-shifted register value,
-// and writes the result to the destination register. It can optionally update
-// the condition flags
-// based on the result.
+// optionally-shifted register value, and writes the result to the destination
+// register. It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6230,10 +6201,9 @@ bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
}
// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
-// the complement of an
-// immediate value, and writes the result to the destination register. It can
-// optionally update the
-// condition flags based on the result.
+// the complement of an immediate value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6306,10 +6276,9 @@ bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
}
// Bitwise Bit Clear (register) performs a bitwise AND of a register value and
-// the complement of an
-// optionally-shifted register value, and writes the result to the destination
-// register.
-// It can optionally update the condition flags based on the result.
+// the complement of an optionally-shifted register value, and writes the
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -6439,7 +6408,7 @@ bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
imm32 = Bits32(opcode, 11, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -6624,7 +6593,7 @@ bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -6661,8 +6630,8 @@ bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
addr_t offset_addr;
addr_t address;
- // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an
- // application level alias for the CPSR".
+ // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
+ // an application level alias for the CPSR".
addr_t offset =
Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
if (!success)
@@ -6968,9 +6937,8 @@ bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
}
// LDRB (register) calculates an address from a base register value and an
-// offset rigister value, loads a byte from
-// memory, zero-extends it to form a 32-bit word, and writes it to a register.
-// The offset register value can
+// offset rigister value, loads a byte from memory, zero-extends it to form a
+// 32-bit word, and writes it to a register. The offset register value can
// optionally be shifted.
bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -7049,7 +7017,7 @@ bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7132,9 +7100,8 @@ bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
// LDRH (immediate, Thumb) calculates an address from a base register value and
// an immediate offset, loads a
-// halfword from memory, zero-extends it to form a 32-bit word, and writes it to
-// a register. It can use offset,
-// post-indexed, or pre-indexed addressing.
+// halfword from memory, zero-extends it to form a 32-bit word, and writes it
+// to a register. It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7384,8 +7351,8 @@ bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
// LDRH (literal) calculates an address from a base register value and an offset
// register value, loads a halfword
// from memory, zero-extends it to form a 32-bit word, and writes it to a
-// register. The offset register value can
-// be shifted left by 0, 1, 2, or 3 bits.
+// register. The offset register value can be shifted left by 0, 1, 2, or 3
+// bits.
bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7464,7 +7431,7 @@ bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7561,8 +7528,7 @@ bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
// LDRSB (immediate) calculates an address from a base register value and an
// immediate offset, loads a byte from
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
-// It can use offset, post-indexed,
-// or pre-indexed addressing.
+// It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7643,7 +7609,7 @@ bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
uint32_t imm4L = Bits32(opcode, 3, 0);
imm32 = (imm4H << 4) | imm4L;
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7799,8 +7765,7 @@ bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
// LDRSB (register) calculates an address from a base register value and an
// offset register value, loadsa byte from
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
-// The offset register value can be
-// shifted left by 0, 1, 2, or 3 bits.
+// The offset register value can be shifted left by 0, 1, 2, or 3 bits.
bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -7873,7 +7838,7 @@ bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -7960,8 +7925,7 @@ bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
// LDRSH (immediate) calculates an address from a base register value and an
// immediate offset, loads a halfword from
// memory, sign-extends it to form a 32-bit word, and writes it to a register.
-// It can use offset, post-indexed, or
-// pre-indexed addressing.
+// It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -8043,7 +8007,7 @@ bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
uint32_t imm4L = Bits32(opcode, 3, 0);
imm32 = (imm4H << 4) | imm4L;
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -8220,8 +8184,8 @@ bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
// LDRSH (register) calculates an address from a base register value and an
// offset register value, loads a halfword
// from memory, sign-extends it to form a 32-bit word, and writes it to a
-// register. The offset register value can be
-// shifted left by 0, 1, 2, or 3 bits.
+// register. The offset register value can be shifted left by 0, 1, 2, or 3
+// bits.
bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -8301,7 +8265,7 @@ bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
n = Bits32(opcode, 19, 16);
m = Bits32(opcode, 3, 0);
- // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
// (W == '1');
index = BitIsSet(opcode, 24);
add = BitIsSet(opcode, 23);
@@ -8879,9 +8843,8 @@ bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
}
// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
-// register value and an immediate value,
-// and writes the result to the destination register. It can optionally update
-// the condition flags based on
+// register value and an immediate value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
// the result.
bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -8957,11 +8920,10 @@ bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
return true;
}
-// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register
-// value and an
-// optionally-shifted register value, and writes the result to the destination
-// register.
-// It can optionally update the condition flags based on the result.
+// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
+// register value and an optionally-shifted register value, and writes the
+// result to the destination register. It can optionally update the condition
+// flags based on the result.
bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9051,10 +9013,8 @@ bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
}
// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
-// and an immediate value, and
-// writes the result to the destination register. It can optionally update the
-// condition flags based
-// on the result.
+// and an immediate value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9128,10 +9088,9 @@ bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
}
// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
-// and an optionally-shifted register
-// value, and writes the result to the destination register. It can optionally
-// update the condition flags based
-// on the result.
+// and an optionally-shifted register value, and writes the result to the
+// destination register. It can optionally update the condition flags based on
+// the result.
bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9219,9 +9178,8 @@ bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
}
// Reverse Subtract (immediate) subtracts a register value from an immediate
-// value, and writes the result to
-// the destination register. It can optionally update the condition flags based
-// on the result.
+// value, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9294,10 +9252,9 @@ bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
return true;
}
-// Reverse Subtract (register) subtracts a register value from an
-// optionally-shifted register value, and writes the
-// result to the destination register. It can optionally update the condition
-// flags based on the result.
+// Reverse Subtract (register) subtracts a register value from an optionally-
+// shifted register value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9377,10 +9334,9 @@ bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
}
// Reverse Subtract with Carry (immediate) subtracts a register value and the
-// value of NOT (Carry flag) from
-// an immediate value, and writes the result to the destination register. It can
-// optionally update the condition
-// flags based on the result.
+// value of NOT (Carry flag) from an immediate value, and writes the result to
+// the destination register. It can optionally update the condition flags based
+// on the result.
bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9440,9 +9396,8 @@ bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
}
// Reverse Subtract with Carry (register) subtracts a register value and the
-// value of NOT (Carry flag) from an
-// optionally-shifted register value, and writes the result to the destination
-// register. It can optionally update the
+// value of NOT (Carry flag) from an optionally-shifted register value, and
+// writes the result to the destination register. It can optionally update the
// condition flags based on the result.
bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
const ARMEncoding encoding) {
@@ -9512,7 +9467,8 @@ bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
return true;
}
-// Subtract with Carry (immediate) subtracts an immediate value and the value of
+// Subtract with Carry (immediate) subtracts an immediate value and the value
+// of
// NOT (Carry flag) from a register value, and writes the result to the
// destination register.
// It can optionally update the condition flags based on the result.
@@ -9582,8 +9538,8 @@ bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
return true;
}
-// Subtract with Carry (register) subtracts an optionally-shifted register value
-// and the value of
+// Subtract with Carry (register) subtracts an optionally-shifted register
+// value and the value of
// NOT (Carry flag) from a register value, and writes the result to the
// destination register.
// It can optionally update the condition flags based on the result.
@@ -9672,9 +9628,8 @@ bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
}
// This instruction subtracts an immediate value from a register value, and
-// writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// writes the result to the destination register. It can optionally update the
+// condition flags based on the result.
bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9766,9 +9721,8 @@ bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
}
// This instruction subtracts an immediate value from a register value, and
-// writes the result
-// to the destination register. It can optionally update the condition flags
-// based on the result.
+// writes the result to the destination register. It can optionally update the
+// condition flags based on the result.
bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9844,9 +9798,8 @@ bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
}
// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
-// register value and an
-// immediate value. It updates the condition flags based on the result, and
-// discards the result.
+// register value and an immediate value. It updates the condition flags based
+// on the result, and discards the result.
bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9904,10 +9857,8 @@ bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
}
// Test Equivalence (register) performs a bitwise exclusive OR operation on a
-// register value and an
-// optionally-shifted register value. It updates the condition flags based on
-// the result, and discards
-// the result.
+// register value and an optionally-shifted register value. It updates the
+// condition flags based on the result, and discards the result.
bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -9972,8 +9923,8 @@ bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
}
// Test (immediate) performs a bitwise AND operation on a register value and an
-// immediate value.
-// It updates the condition flags based on the result, and discards the result.
+// immediate value. It updates the condition flags based on the result, and
+// discards the result.
bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10031,8 +9982,8 @@ bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
}
// Test (register) performs a bitwise AND operation on a register value and an
-// optionally-shifted register value.
-// It updates the condition flags based on the result, and discards the result.
+// optionally-shifted register value. It updates the condition flags based on
+// the result, and discards the result.
bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10403,9 +10354,8 @@ bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
- // if d == 15 then // Can only occur for ARM encoding
- // ALUWritePC(result); // setflags is always FALSE here
- // else
+ // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
+ // // setflags is always FALSE here else
// R[d] = result;
// if setflags then
// APSR.N = result<31>;
@@ -10429,10 +10379,9 @@ bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
}
// A8.6.202 STREX
-// Store Register Exclusive calculates an address from a base register value and
-// an immediate offset, and stores a
-// word from a register to memory if the executing processor has exclusive
-// access to the memory addressed.
+// Store Register Exclusive calculates an address from a base register value
+// and an immediate offset, and stores a word from a register to memory if the
+// executing processor has exclusive access to the memory addressed.
bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10457,7 +10406,8 @@ bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
switch (encoding) {
case eEncodingT1:
- // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00',
+ // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
+ // ZeroExtend(imm8:'00',
// 32);
d = Bits32(opcode, 11, 8);
t = Bits32(opcode, 15, 12);
@@ -10511,9 +10461,9 @@ bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
context.type = eContextRegisterStore;
context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32);
- // if ExclusiveMonitorsPass(address,4) then
- // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the
- // sake of emulation, we will say this
+ // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
+ // (address, addr_byte_size)) -- For now, for the sake of emulation, we
+ // will say this
// always return
// true.
if (true) {
@@ -10742,9 +10692,9 @@ bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
// A8.6.66 LDRD (immediate)
// Load Register Dual (immediate) calculates an address from a base register
-// value and an immediate offset, loads two
-// words from memory, and writes them to two registers. It can use offset,
-// post-indexed, or pre-indexed addressing.
+// value and an immediate offset, loads two words from memory, and writes them
+// to two registers. It can use offset, post-indexed, or pre-indexed
+// addressing.
bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -10891,9 +10841,8 @@ bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
// A8.6.68 LDRD (register)
// Load Register Dual (register) calculates an address from a base register
-// value and a register offset, loads two
-// words from memory, and writes them to two registers. It can use offset,
-// post-indexed or pre-indexed addressing.
+// value and a register offset, loads two words from memory, and writes them to
+// two registers. It can use offset, post-indexed or pre-indexed addressing.
bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -11021,9 +10970,8 @@ bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
// A8.6.200 STRD (immediate)
// Store Register Dual (immediate) calculates an address from a base register
-// value and an immediate offset, and
-// stores two words from two registers to memory. It can use offset,
-// post-indexed, or pre-indexed addressing.
+// value and an immediate offset, and stores two words from two registers to
+// memory. It can use offset, post-indexed, or pre-indexed addressing.
bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -11314,8 +11262,7 @@ bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
// A8.6.319 VLDM
// Vector Load Multiple loads multiple extension registers from consecutive
-// memory locations using an address from
-// an ARM core register.
+// memory locations using an address from an ARM core register.
bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -11328,7 +11275,8 @@ bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
S[d+r] = MemA[address,4]; address = address+4;
else
word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
- // Combine the word-aligned words in the correct order for current endianness.
+ // Combine the word-aligned words in the correct order for
+ // current endianness.
D[d+r] = if BigEndian() then word1:word2 else word2:word1;
#endif
@@ -11389,8 +11337,8 @@ bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
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 =
+ // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
+ // == '1'); d =
// UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet(opcode, 23);
@@ -11519,7 +11467,8 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
if single_regs then
MemA[address,4] = S[d+r]; address = address+4;
else
- // Store as two word-aligned words in the correct order for current endianness.
+ // Store as two word-aligned words in the correct order for
+ // current endianness.
MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
address = address+8;
@@ -11582,8 +11531,8 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
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 =
+ // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
+ // == '1'); d =
// UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet(opcode, 23);
@@ -11665,8 +11614,7 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
address = address + 4;
} else {
// // Store as two word-aligned words in the correct order for current
- // endianness.
- // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
+ // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
// D[d+r]<31:0>;
// MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
// D[d+r]<63:32>;
@@ -11712,8 +11660,7 @@ bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
// A8.6.320
// This instruction loads a single extension register from memory, using an
-// address from an ARM core register, with
-// an optional offset.
+// address from an ARM core register, with an optional offset.
bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -11725,7 +11672,8 @@ bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
S[d] = MemA[address,4];
else
word1 = MemA[address,4]; word2 = MemA[address+4,4];
- // Combine the word-aligned words in the correct order for current endianness.
+ // Combine the word-aligned words in the correct order for current
+ // endianness.
D[d] = if BigEndian() then word1:word2 else word2:word1;
#endif
@@ -11839,8 +11787,7 @@ bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
// A8.6.400 VSTR
// This instruction stores a signle extension register to memory, using an
-// address from an ARM core register, with an
-// optional offset.
+// address from an ARM core register, with an optional offset.
bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -11850,7 +11797,8 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
if single_reg then
MemA[address,4] = S[d];
else
- // Store as two word-aligned words in the correct order for current endianness.
+ // Store as two word-aligned words in the correct order for current
+ // endianness.
MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
#endif
@@ -11970,10 +11918,9 @@ bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
return true;
}
-// A8.6.307 VLDI1 (multiple single elements)
-// This instruction loads elements from memory into one, two, three or four
-// registers, without de-interleaving. Every
-// element of each register is loaded.
+// A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
+// from memory into one, two, three or four registers, without de-interleaving.
+// Every element of each register is loaded.
bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -12291,8 +12238,7 @@ bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
if (index > 0)
mask = mask | Bits64(all_ones, (index * esize) - 1,
0); // add 1's to the right of where 'element' goes.
- // now mask should be 0's where element goes & 1's
- // everywhere else.
+ // now mask should be 0's where element goes & 1's everywhere else.
uint64_t masked_reg =
reg_data & mask; // Take original reg value & zero out 'element' bits
@@ -12307,10 +12253,9 @@ bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
return true;
}
-// A8.6.391 VST1 (multiple single elements)
-// Vector Store (multiple single elements) stores elements to memory from one,
-// two, three, or four registers, without
-// interleaving. Every element of each register is stored.
+// A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
+// elements) stores elements to memory from one, two, three, or four registers,
+// without interleaving. Every element of each register is stored.
bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -12465,8 +12410,8 @@ bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
return true;
}
-// A8.6.392 VST1 (single element from one lane)
-// This instruction stores one element to memory from one element of a register.
+// A8.6.392 VST1 (single element from one lane) This instruction stores one
+// element to memory from one element of a register.
bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
ARMEncoding encoding) {
#if 0
@@ -12624,9 +12569,8 @@ bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
return true;
}
-// A8.6.309 VLD1 (single element to all lanes)
-// This instruction loads one element from memory into every element of one or
-// two vectors.
+// A8.6.309 VLD1 (single element to all lanes) This instruction loads one
+// element from memory into every element of one or two vectors.
bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -12754,11 +12698,10 @@ bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
return true;
}
-// B6.2.13 SUBS PC, LR and related instructions
-// The SUBS PC, LR, #<const? instruction provides an exception return without
-// the use of the stack. It subtracts the
-// immediate constant from the LR, branches to the resulting address, and also
-// copies the SPSR to the CPSR.
+// B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
+// instruction provides an exception return without the use of the stack. It
+// subtracts the immediate constant from the LR, branches to the resulting
+// address, and also copies the SPSR to the CPSR.
bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
const ARMEncoding encoding) {
#if 0
@@ -12797,9 +12740,9 @@ bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
switch (encoding) {
case eEncodingT1:
- // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
- // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode =
- // '0010'; // = SUB
+ // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
+ // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
+ // // = SUB
n = 14;
imm32 = Bits32(opcode, 7, 0);
register_form = false;
@@ -12924,8 +12867,7 @@ bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
// 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.
+ // use the CPSR instead, and hope for the best.
uint32_t spsr =
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
if (!success)
@@ -13946,10 +13888,10 @@ bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
else {
AddressClass addr_class = inst_addr.GetAddressClass();
- if ((addr_class == eAddressClassCode) ||
- (addr_class == eAddressClassUnknown))
+ if ((addr_class == AddressClass::eCode) ||
+ (addr_class == AddressClass::eUnknown))
m_opcode_mode = eModeARM;
- else if (addr_class == eAddressClassCodeAlternateISA)
+ else if (addr_class == AddressClass::eCodeAlternateISA)
m_opcode_mode = eModeThumb;
else
return false;
@@ -13999,8 +13941,7 @@ bool EmulateInstructionARM::ReadInstruction() {
if (!m_ignore_conditions) {
// If we are not ignoreing the conditions then init the it session from
- // the current
- // value of cpsr.
+ // the current value of cpsr.
uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |
Bits32(m_opcode_cpsr, 26, 25);
if (it != 0)
@@ -14018,10 +13959,9 @@ bool EmulateInstructionARM::ReadInstruction() {
uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
bool 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
- // emulate an instruction even if we don't have all the right
- // bits set in the CPSR register...
+ // If we are ignoring conditions, then always return true. this allows us to
+ // iterate over disassembly code and still emulate an instruction even if we
+ // don't have all the right bits set in the CPSR register...
if (m_ignore_conditions)
return true;
@@ -14225,8 +14165,8 @@ bool EmulateInstructionARM::BranchWritePC(const Context &context,
bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
addr_t target;
// If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
- // we want to record it and issue a WriteRegister callback so the clients
- // can track the mode changes accordingly.
+ // we want to record it and issue a WriteRegister callback so the clients can
+ // track the mode changes accordingly.
bool cpsr_changed = false;
if (BitIsSet(addr, 0)) {
@@ -14307,9 +14247,10 @@ bool EmulateInstructionARM::UnalignedSupport() {
return (ArchVersion() >= ARMv7);
}
-// The main addition and subtraction instructions can produce status information
-// about both unsigned carry and signed overflow conditions. This status
-// information can be used to synthesize multi-word additions and subtractions.
+// The main addition and subtraction instructions can produce status
+// information about both unsigned carry and signed overflow conditions. This
+// status information can be used to synthesize multi-word additions and
+// subtractions.
EmulateInstructionARM::AddWithCarryResult
EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
uint32_t result;
@@ -14364,9 +14305,8 @@ uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
// When executing an ARM instruction , PC reads as the address of the current
- // instruction plus 8.
- // When executing a Thumb instruction , PC reads as the address of the current
- // instruction plus 4.
+ // instruction plus 8. When executing a Thumb instruction , PC reads as the
+ // address of the current instruction plus 4.
if (num == 15) {
if (CurrentInstrSet() == eModeARM)
val += 8;
@@ -14434,8 +14374,7 @@ bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
// APSR.V = overflow
//
// Default arguments can be specified for carry and overflow parameters, which
-// means
-// not to update the respective flags.
+// means not to update the respective flags.
bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
const uint32_t carry,
const uint32_t overflow) {
@@ -14496,8 +14435,7 @@ bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
}
// Advance the ITSTATE bits to their values for the next instruction if we
- // haven't just executed
- // an IT instruction what initialized it.
+ // haven't just executed an IT instruction what initialized it.
if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
(opcode_data == nullptr ||
opcode_data->callback != &EmulateInstructionARM::EmulateIT))
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
index d882108c25f4..2f484ab5ea97 100644
--- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
@@ -76,19 +76,6 @@ static inline bool IsZero(uint64_t x) { return x == 0; }
static inline uint64_t NOT(uint64_t x) { return ~x; }
-#if 0
-// LSL_C()
-// =======
-static inline uint64_t
-LSL_C (uint64_t x, integer shift, bool &carry_out)
-{
- assert (shift >= 0);
- uint64_t result = x << shift;
- carry_out = ((1ull << (64-1)) >> (shift - 1)) != 0;
- return result;
-}
-#endif
-
// LSL()
// =====
@@ -519,8 +506,8 @@ bool EmulateInstructionARM64::UsingAArch32() {
bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N,
addr_t target) {
#if 0
- // Set program counter to a new address, with a branch reason hint
- // for possible use by hardware fetching the next instruction.
+ // Set program counter to a new address, with a branch reason hint for
+ // possible use by hardware fetching the next instruction.
BranchTo(bits(N) target, BranchType branch_type)
Hint_Branch(branch_type);
if N == 32 then
@@ -568,10 +555,9 @@ bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N,
}
bool EmulateInstructionARM64::ConditionHolds(const uint32_t cond) {
- // If we are ignoring conditions, then always return true.
- // this allows us to iterate over disassembly code and still
- // emulate an instruction even if we don't have all the right
- // bits set in the CPSR register...
+ // If we are ignoring conditions, then always return true. this allows us to
+ // iterate over disassembly code and still emulate an instruction even if we
+ // don't have all the right bits set in the CPSR register...
if (m_ignore_conditions)
return true;
@@ -703,8 +689,8 @@ bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) {
context.SetRegisterPlusOffset(reg_info_Rn, imm);
if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) {
- // 'mov sp, fp' - common epilogue instruction, CFA is now in terms
- // of the stack pointer, instead of frame pointer.
+ // 'mov sp, fp' - common epilogue instruction, CFA is now in terms of the
+ // stack pointer, instead of frame pointer.
context.type = EmulateInstruction::eContextRestoreStackPointer;
} else if ((n == gpr_sp_arm64 || n == GetFramePointerRegisterNumber()) &&
d == gpr_sp_arm64 && !setflags) {
diff --git a/source/Plugins/Instruction/CMakeLists.txt b/source/Plugins/Instruction/CMakeLists.txt
index 78f2f64cf1ab..89771e8f46d1 100644
--- a/source/Plugins/Instruction/CMakeLists.txt
+++ b/source/Plugins/Instruction/CMakeLists.txt
@@ -2,3 +2,4 @@ add_subdirectory(ARM)
add_subdirectory(ARM64)
add_subdirectory(MIPS)
add_subdirectory(MIPS64)
+add_subdirectory(PPC64)
diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index db3d8fc1b8ca..b65747e12890 100644
--- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -1015,7 +1015,7 @@ bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
m_use_alt_disaasm = false;
if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
- if (inst_addr.GetAddressClass() == eAddressClassCodeAlternateISA) {
+ if (inst_addr.GetAddressClass() == AddressClass::eCodeAlternateISA) {
Status error;
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
@@ -1044,7 +1044,7 @@ bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode,
return true;
} else {
/*
- * If the address class is not eAddressClassCodeAlternateISA then
+ * If the address class is not AddressClass::eCodeAlternateISA then
* the function is not microMIPS. In this case instruction size is
* always 4 bytes.
*/
@@ -1205,13 +1205,10 @@ bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) {
dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
- // If immediate value is greater then 2^16 - 1 then clang generate
- // LUI, ADDIU, SUBU instructions in prolog.
- // Example
- // lui $1, 0x2
- // addiu $1, $1, -0x5920
- // subu $sp, $sp, $1
- // In this case, ADDIU dst and src will be same and not equal to sp
+ // If immediate value is greater then 2^16 - 1 then clang generate LUI,
+ // ADDIU, SUBU instructions in prolog. Example lui $1, 0x2 addiu $1, $1,
+ // -0x5920 subu $sp, $sp, $1 In this case, ADDIU dst and src will be same
+ // and not equal to sp
if (dst == src) {
Context context;
@@ -1545,8 +1542,8 @@ bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) {
address = address + imm5;
// We use bad_vaddr_context to store base address which is used by H/W
- // watchpoint
- // Set the bad_vaddr register with base address used in the instruction
+ // watchpoint Set the bad_vaddr register with base address used in the
+ // instruction
bad_vaddr_context.type = eContextInvalid;
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
address);
@@ -1682,8 +1679,8 @@ bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {
base_address = base_address + imm5;
// We use bad_vaddr_context to store base address which is used by H/W
- // watchpoint
- // Set the bad_vaddr register with base address used in the instruction
+ // watchpoint Set the bad_vaddr register with base address used in the
+ // instruction
bad_vaddr_context.type = eContextInvalid;
WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips,
base_address);
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index d298589afdd9..5af12ad141aa 100644
--- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -1091,13 +1091,10 @@ bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg());
src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg());
- // If immediate is greater than 2^16 - 1 then clang generate
- // LUI, (D)ADDIU,(D)SUBU instructions in prolog.
- // Example
- // lui $1, 0x2
- // daddiu $1, $1, -0x5920
- // dsubu $sp, $sp, $1
- // In this case, (D)ADDIU dst and src will be same and not equal to sp
+ // If immediate is greater than 2^16 - 1 then clang generate LUI,
+ // (D)ADDIU,(D)SUBU instructions in prolog. Example lui $1, 0x2 daddiu $1,
+ // $1, -0x5920 dsubu $sp, $sp, $1 In this case, (D)ADDIU dst and src will be
+ // same and not equal to sp
if (dst == src) {
Context context;
diff --git a/source/Plugins/Instruction/PPC64/CMakeLists.txt b/source/Plugins/Instruction/PPC64/CMakeLists.txt
new file mode 100644
index 000000000000..0926433fc77c
--- /dev/null
+++ b/source/Plugins/Instruction/PPC64/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginInstructionPPC64 PLUGIN
+ EmulateInstructionPPC64.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbInterpreter
+ lldbSymbol
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
new file mode 100644
index 000000000000..f3a9ca570a4a
--- /dev/null
+++ b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
@@ -0,0 +1,406 @@
+//===-- EmulateInstructionPPC64.cpp ------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulateInstructionPPC64.h"
+
+#include <stdlib.h>
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/ConstString.h"
+
+#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
+
+#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+EmulateInstructionPPC64::EmulateInstructionPPC64(const ArchSpec &arch)
+ : EmulateInstruction(arch) {}
+
+void EmulateInstructionPPC64::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+}
+
+void EmulateInstructionPPC64::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString EmulateInstructionPPC64::GetPluginNameStatic() {
+ ConstString g_plugin_name("lldb.emulate-instruction.ppc64");
+ return g_plugin_name;
+}
+
+ConstString EmulateInstructionPPC64::GetPluginName() {
+ static ConstString g_plugin_name("EmulateInstructionPPC64");
+ return g_plugin_name;
+}
+
+const char *EmulateInstructionPPC64::GetPluginDescriptionStatic() {
+ return "Emulate instructions for the PPC64 architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch,
+ InstructionType inst_type) {
+ if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic(
+ inst_type)) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64 ||
+ arch.GetTriple().getArch() == llvm::Triple::ppc64le) {
+ return new EmulateInstructionPPC64(arch);
+ }
+ }
+
+ return nullptr;
+}
+
+bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64)
+ return true;
+ else if (arch.GetTriple().getArch() == llvm::Triple::ppc64le)
+ return true;
+
+ return false;
+}
+
+static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo &reg_info) {
+ if (reg_num >= llvm::array_lengthof(g_register_infos_ppc64le))
+ return false;
+ reg_info = g_register_infos_ppc64le[reg_num];
+ return true;
+}
+
+bool EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind,
+ uint32_t reg_num,
+ RegisterInfo &reg_info) {
+ if (reg_kind == eRegisterKindGeneric) {
+ switch (reg_num) {
+ case LLDB_REGNUM_GENERIC_PC:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_pc_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_SP:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_r1_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_RA:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_lr_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_FLAGS:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_cr_ppc64le;
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ if (reg_kind == eRegisterKindLLDB)
+ return LLDBTableGetRegisterInfo(reg_num, reg_info);
+ return false;
+}
+
+bool EmulateInstructionPPC64::ReadInstruction() {
+ bool success = false;
+ m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
+ LLDB_INVALID_ADDRESS, &success);
+ if (success) {
+ Context ctx;
+ ctx.type = eContextReadOpcode;
+ ctx.SetNoArgs();
+ m_opcode.SetOpcode32(ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success),
+ GetByteOrder());
+ }
+ if (!success)
+ m_addr = LLDB_INVALID_ADDRESS;
+ return success;
+}
+
+bool EmulateInstructionPPC64::CreateFunctionEntryUnwind(
+ UnwindPlan &unwind_plan) {
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind(eRegisterKindLLDB);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our previous Call Frame Address is the stack pointer
+ row->GetCFAValue().SetIsRegisterPlusOffset(gpr_r1_ppc64le, 0);
+
+ unwind_plan.AppendRow(row);
+ unwind_plan.SetSourceName("EmulateInstructionPPC64");
+ unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le);
+ return true;
+}
+
+EmulateInstructionPPC64::Opcode *
+EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) {
+ static EmulateInstructionPPC64::Opcode g_opcodes[] = {
+ {0xfc0007ff, 0x7c0002a6, &EmulateInstructionPPC64::EmulateMFSPR,
+ "mfspr RT, SPR"},
+ {0xfc000003, 0xf8000000, &EmulateInstructionPPC64::EmulateSTD,
+ "std RS, DS(RA)"},
+ {0xfc000003, 0xf8000001, &EmulateInstructionPPC64::EmulateSTD,
+ "stdu RS, DS(RA)"},
+ {0xfc0007fe, 0x7c000378, &EmulateInstructionPPC64::EmulateOR,
+ "or RA, RS, RB"},
+ {0xfc000000, 0x38000000, &EmulateInstructionPPC64::EmulateADDI,
+ "addi RT, RA, SI"},
+ {0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD,
+ "ld RT, DS(RA)"}};
+ static const size_t k_num_ppc_opcodes = llvm::array_lengthof(g_opcodes);
+
+ for (size_t i = 0; i < k_num_ppc_opcodes; ++i) {
+ if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
+ return &g_opcodes[i];
+ }
+ return nullptr;
+}
+
+bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) {
+ const uint32_t opcode = m_opcode.GetOpcode32();
+ // LLDB_LOG(log, "PPC64::EvaluateInstruction: opcode={0:X+8}", opcode);
+ Opcode *opcode_data = GetOpcodeForInstruction(opcode);
+ if (!opcode_data)
+ return false;
+
+ // LLDB_LOG(log, "PPC64::EvaluateInstruction: {0}", opcode_data->name);
+ const bool auto_advance_pc =
+ evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+
+ bool success = false;
+
+ uint32_t orig_pc_value = 0;
+ if (auto_advance_pc) {
+ orig_pc_value =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ }
+
+ // Call the Emulate... function.
+ success = (this->*opcode_data->callback)(opcode);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc) {
+ uint32_t new_pc_value =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc && (new_pc_value == orig_pc_value)) {
+ EmulateInstruction::Context context;
+ context.type = eContextAdvancePC;
+ context.SetNoArgs();
+ if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_ppc64le,
+ orig_pc_value + 4))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateMFSPR(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t spr = Bits32(opcode, 20, 11);
+
+ enum { SPR_LR = 0x100 };
+
+ // For now, we're only insterested in 'mfspr r0, lr'
+ if (rt != gpr_r0_ppc64le || spr != SPR_LR)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateMFSPR: {0:X+8}: mfspr r0, lr", m_addr);
+
+ bool success;
+ uint64_t lr =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ Context context;
+ context.type = eContextWriteRegisterRandomBits;
+ WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_r0_ppc64le, lr);
+ LLDB_LOG(log, "EmulateMFSPR: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateLD(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t ds = Bits32(opcode, 15, 2);
+
+ int32_t ids = llvm::SignExtend32<16>(ds << 2);
+
+ // For now, tracking only loads from 0(r1) to r1 (0(r1) is the ABI defined
+ // location to save previous SP)
+ if (ra != gpr_r1_ppc64le || rt != gpr_r1_ppc64le || ids != 0)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateLD: {0:X+8}: ld r{1}, {2}(r{3})", m_addr, rt, ids, ra);
+
+ RegisterInfo r1_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
+ return false;
+
+ // restore SP
+ Context ctx;
+ ctx.type = eContextRestoreStackPointer;
+ ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
+
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0);
+ LLDB_LOG(log, "EmulateLD: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) {
+ uint32_t rs = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t ds = Bits32(opcode, 15, 2);
+ uint32_t u = Bits32(opcode, 1, 0);
+
+ // For now, tracking only stores to r1
+ if (ra != gpr_r1_ppc64le)
+ return false;
+ // ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr)
+ if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le &&
+ rs != gpr_r0_ppc64le)
+ return false;
+
+ bool success;
+ uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success);
+ if (!success)
+ return false;
+
+ int32_t ids = llvm::SignExtend32<16>(ds << 2);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr,
+ u ? "u" : "", rs, ids, ra);
+
+ // Make sure that r0 is really holding LR value (this won't catch unlikely
+ // cases, such as r0 being overwritten after mfspr)
+ uint32_t rs_num = rs;
+ if (rs == gpr_r0_ppc64le) {
+ uint64_t lr =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
+ if (!success || lr != rs_val)
+ return false;
+ rs_num = gpr_lr_ppc64le;
+ }
+
+ // set context
+ RegisterInfo rs_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, rs_num, rs_info))
+ return false;
+ RegisterInfo ra_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextPushRegisterOnStack;
+ ctx.SetRegisterToRegisterPlusOffset(rs_info, ra_info, ids);
+
+ // store
+ uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success);
+ if (!success)
+ return false;
+
+ lldb::addr_t addr = ra_val + ids;
+ WriteMemory(ctx, addr, &rs_val, sizeof(rs_val));
+
+ // update RA?
+ if (u) {
+ Context ctx;
+ // NOTE Currently, RA will always be equal to SP(r1)
+ ctx.type = eContextAdjustStackPointer;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr);
+ }
+
+ LLDB_LOG(log, "EmulateSTD: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) {
+ uint32_t rs = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t rb = Bits32(opcode, 15, 11);
+
+ // to be safe, process only the known 'mr r31/r30, r1' prologue instructions
+ if (m_fp != LLDB_INVALID_REGNUM || rs != rb ||
+ (ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb);
+
+ // set context
+ RegisterInfo ra_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextSetFramePointer;
+ ctx.SetRegister(ra_info);
+
+ // move
+ bool success;
+ uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success);
+ if (!success)
+ return false;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val);
+ m_fp = ra;
+ LLDB_LOG(log, "EmulateOR: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t si = Bits32(opcode, 15, 0);
+
+ // handle stack adjustments only
+ // (this is a typical epilogue operation, with ra == r1. If it's
+ // something else, then we won't know the correct value of ra)
+ if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le)
+ return false;
+
+ int32_t si_val = llvm::SignExtend32<16>(si);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val);
+
+ // set context
+ RegisterInfo r1_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextRestoreStackPointer;
+ ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
+
+ // adjust SP
+ bool success;
+ uint64_t r1 =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val);
+ LLDB_LOG(log, "EmulateADDI: success!");
+ return true;
+}
diff --git a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
new file mode 100644
index 000000000000..be65de9a5063
--- /dev/null
+++ b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
@@ -0,0 +1,97 @@
+//===-- EmulateInstructionPPC64.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EmulateInstructionPPC64_h_
+#define EmulateInstructionPPC64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Interpreter/OptionValue.h"
+#include "lldb/Utility/Log.h"
+
+namespace lldb_private {
+
+class EmulateInstructionPPC64 : public EmulateInstruction {
+public:
+ EmulateInstructionPPC64(const ArchSpec &arch);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static EmulateInstruction *CreateInstance(const ArchSpec &arch,
+ InstructionType inst_type);
+
+ static bool
+ SupportsEmulatingInstructionsOfTypeStatic(InstructionType inst_type) {
+ switch (inst_type) {
+ case eInstructionTypeAny:
+ case eInstructionTypePrologueEpilogue:
+ return true;
+
+ case eInstructionTypePCModifying:
+ case eInstructionTypeAll:
+ return false;
+ }
+ return false;
+ }
+
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override { return 1; }
+
+ bool SetTargetTriple(const ArchSpec &arch) override;
+
+ bool SupportsEmulatingInstructionsOfType(InstructionType inst_type) override {
+ return SupportsEmulatingInstructionsOfTypeStatic(inst_type);
+ }
+
+ bool ReadInstruction() override;
+
+ bool EvaluateInstruction(uint32_t evaluate_options) override;
+
+ bool TestEmulation(Stream *out_stream, ArchSpec &arch,
+ OptionValueDictionary *test_data) override {
+ return false;
+ }
+
+ bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num,
+ RegisterInfo &reg_info) override;
+
+ bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) override;
+
+private:
+ struct Opcode {
+ uint32_t mask;
+ uint32_t value;
+ bool (EmulateInstructionPPC64::*callback)(uint32_t opcode);
+ const char *name;
+ };
+
+ uint32_t m_fp = LLDB_INVALID_REGNUM;
+
+ Opcode *GetOpcodeForInstruction(uint32_t opcode);
+
+ bool EmulateMFSPR(uint32_t opcode);
+ bool EmulateLD(uint32_t opcode);
+ bool EmulateSTD(uint32_t opcode);
+ bool EmulateOR(uint32_t opcode);
+ bool EmulateADDI(uint32_t opcode);
+};
+
+} // namespace lldb_private
+
+#endif // EmulateInstructionPPC64_h_
diff --git a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
index eb238419ab18..32da327ee465 100644
--- a/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
@@ -267,8 +267,8 @@ MainThreadCheckerRuntime::GetBacktracesFromExtendedStopInfo(
new HistoryThread(*process_sp, tid, PCs, stop_id, stop_id_is_valid);
ThreadSP new_thread_sp(history_thread);
- // Save this in the Process' ExtendedThreadList so a strong pointer
- // retains the object
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains
+ // the object
process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
threads->AddThread(new_thread_sp);
diff --git a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
index cf9ba60c7b60..6ce50f5c6839 100644
--- a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
@@ -282,9 +282,8 @@ GetRenumberedThreadIds(ProcessSP process_sp, ValueObjectSP data,
} else {
// This isn't a live thread anymore. Ask process to assign a new
// Index ID (or return an old one if we've already seen this
- // thread_os_id).
- // It will also make sure that no new threads are assigned this Index
- // ID.
+ // thread_os_id). It will also make sure that no new threads are
+ // assigned this Index ID.
lldb_user_id = process_sp->AssignIndexIDToThread(thread_os_id);
}
@@ -574,7 +573,7 @@ static void GetSymbolDeclarationFromAddress(ProcessSP process_sp, addr_t addr,
return;
VariableList var_list;
- module->FindGlobalVariables(sym_name, nullptr, true, 1U, var_list);
+ module->FindGlobalVariables(sym_name, nullptr, 1U, var_list);
if (var_list.GetSize() < 1)
return;
diff --git a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
index 28c28e41ef44..1e9280c8c064 100644
--- a/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
@@ -334,8 +334,8 @@ UndefinedBehaviorSanitizerRuntime::GetBacktracesFromExtendedStopInfo(
std::string stop_reason_description = GetStopReasonDescription(info);
new_thread_sp->SetName(stop_reason_description.c_str());
- // Save this in the Process' ExtendedThreadList so a strong pointer
- // retains the object
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains
+ // the object
process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
threads->AddThread(new_thread_sp);
diff --git a/source/Plugins/JITLoader/GDB/CMakeLists.txt b/source/Plugins/JITLoader/GDB/CMakeLists.txt
index 25e8d1ee231f..190599cbd588 100644
--- a/source/Plugins/JITLoader/GDB/CMakeLists.txt
+++ b/source/Plugins/JITLoader/GDB/CMakeLists.txt
@@ -1,5 +1,3 @@
-include_directories(.)
-
add_lldb_library(lldbPluginJITLoaderGDB PLUGIN
JITLoaderGDB.cpp
diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
index 5e8f051dec98..82b7ac1675fa 100644
--- a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
+++ b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
@@ -147,9 +147,8 @@ public:
return child_sp;
}
- // return true if this object is now safe to use forever without
- // ever updating again; the typical (and tested) answer here is
- // 'false'
+ // return true if this object is now safe to use forever without ever
+ // updating again; the typical (and tested) answer here is 'false'
bool Update() override { return false; }
// maybe return false if the block pointer is, say, null
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 51ed88065c84..2c63e6467d4c 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -120,10 +120,9 @@ static bool ReverseFindMatchingChars(const llvm::StringRef &s,
static bool IsTrivialBasename(const llvm::StringRef &basename) {
// Check that the basename matches with the following regular expression
- // "^~?([A-Za-z_][A-Za-z_0-9]*)$"
- // We are using a hand written implementation because it is significantly more
- // efficient then
- // using the general purpose regular expression library.
+ // "^~?([A-Za-z_][A-Za-z_0-9]*)$" We are using a hand written implementation
+ // because it is significantly more efficient then using the general purpose
+ // regular expression library.
size_t idx = 0;
if (basename.size() > 0 && basename[0] == '~')
idx = 1;
@@ -151,10 +150,9 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) {
}
bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
- // This method tries to parse simple method definitions
- // which are presumably most comman in user programs.
- // Definitions that can be parsed by this function don't have return types
- // and templates in the name.
+ // This method tries to parse simple method definitions which are presumably
+ // most comman in user programs. Definitions that can be parsed by this
+ // function don't have return types and templates in the name.
// A::B::C::fun(std::vector<T> &) const
size_t arg_start, arg_end;
llvm::StringRef full(m_full.GetCString());
@@ -251,13 +249,17 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
}
bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
- // FIXME, we should really run through all the known C++ Language plugins and
- // ask each one if
- // this is a C++ mangled name, but we can put that off till there is actually
- // more than one
- // we care about.
-
- return (name != nullptr && name[0] == '_' && name[1] == 'Z');
+ // FIXME!! we should really run through all the known C++ Language plugins
+ // and ask each one if this is a C++ mangled name
+
+ if (name == nullptr)
+ return false;
+
+ // MSVC style mangling
+ if (name[0] == '?')
+ return true;
+
+ return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
}
bool CPlusPlusLanguage::ExtractContextAndIdentifier(
@@ -307,13 +309,15 @@ static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
// FastDemangle will call our hook for each instance of a primitive type,
// allowing us to perform substitution
- const char *const demangled =
+ char *const demangled =
FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
if (log)
log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
mangled.str().c_str(), demangled, output_buf.c_str(),
FastDemangle(output_buf.c_str()));
+ // FastDemangle malloc'd this string.
+ free(demangled);
return output_buf == mangled ? ConstString() : ConstString(output_buf);
}
@@ -419,18 +423,20 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
SyntheticChildren::Flags stl_synth_flags;
stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
false);
+ SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;
+ stl_deref_flags.SetFrontEndWantsDereference();
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
"libc++ std::bitset synthetic children",
- ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
"libc++ std::vector synthetic children",
- ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
@@ -453,13 +459,13 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
cpp_category_sp,
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
"libc++ std::set synthetic children",
- ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
"libc++ std::multiset synthetic children",
- ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_synth_flags,
+ ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_deref_flags,
true);
AddCXXSynthetic(
cpp_category_sp,
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
index aebea6ae3569..b32fe9588965 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
@@ -25,8 +25,8 @@ Optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() {
m_next_token_index = 0;
Optional<ParsedFunction> result(None);
- // Try to parse the name as function without a return type specified
- // e.g. main(int, char*[])
+ // Try to parse the name as function without a return type specified e.g.
+ // main(int, char*[])
{
Bookmark start_position = SetBookmark();
result = ParseFunctionImpl(false);
@@ -34,8 +34,8 @@ Optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() {
return result;
}
- // Try to parse the name as function with function pointer return type
- // e.g. void (*get_func(const char*))()
+ // Try to parse the name as function with function pointer return type e.g.
+ // void (*get_func(const char*))()
result = ParseFuncPtr(true);
if (result)
return result;
@@ -183,13 +183,13 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() {
Advance();
// Consuming template arguments is a bit trickier than consuming function
- // arguments, because '<' '>' brackets are not always trivially balanced.
- // In some rare cases tokens '<' and '>' can appear inside template arguments
- // as arithmetic or shift operators not as template brackets.
- // Examples: std::enable_if<(10u)<(64), bool>
+ // arguments, because '<' '>' brackets are not always trivially balanced. In
+ // some rare cases tokens '<' and '>' can appear inside template arguments as
+ // arithmetic or shift operators not as template brackets. Examples:
+ // std::enable_if<(10u)<(64), bool>
// f<A<operator<(X,Y)::Subclass>>
- // Good thing that compiler makes sure that really ambiguous cases of
- // '>' usage should be enclosed within '()' brackets.
+ // Good thing that compiler makes sure that really ambiguous cases of '>'
+ // usage should be enclosed within '()' brackets.
int template_counter = 1;
bool can_open_template = false;
while (HasMoreTokens() && template_counter > 0) {
@@ -208,9 +208,9 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() {
case tok::less:
// '<' is an attempt to open a subteamplte
// check if parser is at the point where it's actually possible,
- // otherwise it's just a part of an expression like 'sizeof(T)<(10)'.
- // No need to do the same for '>' because compiler actually makes sure
- // that '>' always surrounded by brackets to avoid ambiguity.
+ // otherwise it's just a part of an expression like 'sizeof(T)<(10)'. No
+ // need to do the same for '>' because compiler actually makes sure that
+ // '>' always surrounded by brackets to avoid ambiguity.
if (can_open_template)
++template_counter;
can_open_template = false;
@@ -242,8 +242,7 @@ bool CPlusPlusNameParser::ConsumeTemplateArgs() {
}
}
- assert(template_counter >= 0);
- if (template_counter > 0) {
+ if (template_counter != 0) {
return false;
}
start_position.Remove();
@@ -389,10 +388,9 @@ void CPlusPlusNameParser::SkipFunctionQualifiers() {
bool CPlusPlusNameParser::ConsumeBuiltinType() {
bool result = false;
bool continue_parsing = true;
- // Built-in types can be made of a few keywords
- // like 'unsigned long long int'. This function
- // consumes all built-in type keywords without
- // checking if they make sense like 'unsigned char void'.
+ // Built-in types can be made of a few keywords like 'unsigned long long
+ // int'. This function consumes all built-in type keywords without checking
+ // if they make sense like 'unsigned char void'.
while (continue_parsing && HasMoreTokens()) {
switch (Peek().getKind()) {
case tok::kw_short:
diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index f6d1f18cb596..95e02a473cd7 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -123,12 +123,11 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
static ConstString g___i_("__i_");
- // this must be a ValueObject* because it is a child of the ValueObject we are
- // producing children for
- // it if were a ValueObjectSP, we would end up with a loop (iterator ->
- // synthetic -> child -> parent == iterator)
- // and that would in turn leak memory by never allowing the ValueObjects to
- // die and free their memory
+ // this must be a ValueObject* because it is a child of the ValueObject we
+ // are producing children for it if were a ValueObjectSP, we would end up
+ // with a loop (iterator -> synthetic -> child -> parent == iterator) and
+ // that would in turn leak memory by never allowing the ValueObjects to die
+ // and free their memory
m_pair_ptr = valobj_sp
->GetValueForExpressionPath(
".__i_.__ptr_->__value_", nullptr, nullptr,
@@ -386,7 +385,8 @@ enum LibcxxStringLayoutMode {
};
// this function abstracts away the layout and mode details of a libc++ string
-// and returns the address of the data and the size ready for callers to consume
+// and returns the address of the data and the size ready for callers to
+// consume
static bool ExtractLibcxxStringInfo(ValueObject &valobj,
ValueObjectSP &location_sp,
uint64_t &size) {
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 6407ae129ad7..6066f14b18cc 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -206,8 +206,7 @@ bool AbstractListFrontEnd::HasLoop(size_t count) {
if (m_loop_detected == 0) {
// This is the first time we are being run (after the last update). Set up
- // the loop
- // invariant for the first element.
+ // the loop invariant for the first element.
m_slow_runner = ListEntry(m_head).next();
m_fast_runner = m_slow_runner.next();
m_loop_detected = 1;
@@ -215,9 +214,8 @@ bool AbstractListFrontEnd::HasLoop(size_t count) {
// Loop invariant:
// Loop detection has been run over the first m_loop_detected elements. If
- // m_slow_runner ==
- // m_fast_runner then the loop has been detected after m_loop_detected
- // elements.
+ // m_slow_runner == m_fast_runner then the loop has been detected after
+ // m_loop_detected elements.
const size_t steps_to_run = std::min(count, m_count);
while (m_loop_detected < steps_to_run && m_slow_runner && m_fast_runner &&
m_slow_runner != m_fast_runner) {
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index be96a6d95bcd..8f82bdcbfd59 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -382,8 +382,8 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex(
return lldb::ValueObjectSP();
}
} else {
- // because of the way our debug info is made, we need to read item 0 first
- // so that we can cache information used to generate other elements
+ // because of the way our debug info is made, we need to read item 0
+ // first so that we can cache information used to generate other elements
if (m_skip_size == UINT32_MAX)
GetChildAtIndex(0);
if (m_skip_size == UINT32_MAX) {
diff --git a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
index b6d664df16ef..9d46e3e3ee58 100644
--- a/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibStdcppUniquePointer.cpp
@@ -43,6 +43,8 @@ private:
ValueObjectSP m_ptr_obj;
ValueObjectSP m_obj_obj;
ValueObjectSP m_del_obj;
+
+ ValueObjectSP GetTuple();
};
} // end of anonymous namespace
@@ -53,17 +55,36 @@ LibStdcppUniquePtrSyntheticFrontEnd::LibStdcppUniquePtrSyntheticFrontEnd(
Update();
}
-bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
+ValueObjectSP LibStdcppUniquePtrSyntheticFrontEnd::GetTuple() {
ValueObjectSP valobj_backend_sp = m_backend.GetSP();
+
if (!valobj_backend_sp)
- return false;
+ return nullptr;
ValueObjectSP valobj_sp = valobj_backend_sp->GetNonSyntheticValue();
if (!valobj_sp)
- return false;
+ return nullptr;
- ValueObjectSP tuple_sp =
+ ValueObjectSP obj_child_sp =
valobj_sp->GetChildMemberWithName(ConstString("_M_t"), true);
+ if (!obj_child_sp)
+ return nullptr;
+
+ ValueObjectSP obj_subchild_sp =
+ obj_child_sp->GetChildMemberWithName(ConstString("_M_t"), true);
+
+ // if there is a _M_t subchild, the tuple is found in the obj_subchild_sp
+ // (for libstdc++ 6.0.23).
+ if (obj_subchild_sp) {
+ return obj_subchild_sp;
+ }
+
+ return obj_child_sp;
+}
+
+bool LibStdcppUniquePtrSyntheticFrontEnd::Update() {
+ ValueObjectSP tuple_sp = GetTuple();
+
if (!tuple_sp)
return false;
diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp
index 8f4997533212..8f278fc2d513 100644
--- a/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -67,12 +67,12 @@ bool lldb_private::formatters::NSBundleSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "NSBundle")) {
+ if (class_name == "NSBundle") {
uint64_t offset = 5 * ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(
offset,
@@ -117,12 +117,12 @@ bool lldb_private::formatters::NSTimeZoneSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "__NSTimeZone")) {
+ if (class_name == "__NSTimeZone") {
uint64_t offset = ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(
offset, valobj.GetCompilerType(), true));
@@ -164,12 +164,12 @@ bool lldb_private::formatters::NSNotificationSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "NSConcreteNotification")) {
+ if (class_name == "NSConcreteNotification") {
uint64_t offset = ptr_size;
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(
offset, valobj.GetCompilerType(), true));
@@ -211,14 +211,14 @@ bool lldb_private::formatters::NSMachPortSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
uint64_t port_number = 0;
- if (!strcmp(class_name, "NSMachPort")) {
+ if (class_name == "NSMachPort") {
uint64_t offset = (ptr_size == 4 ? 12 : 20);
Status error;
port_number = process_sp->ReadUnsignedIntegerFromMemory(
@@ -259,16 +259,15 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
uint64_t count = 0;
do {
- if (!strcmp(class_name, "NSIndexSet") ||
- !strcmp(class_name, "NSMutableIndexSet")) {
+ if (class_name == "NSIndexSet" || class_name == "NSMutableIndexSet") {
Status error;
uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(
valobj_addr + ptr_size, 4, 0, error);
@@ -451,15 +450,18 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
if (!valobj_addr)
return false;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name(descriptor->GetClassName().GetCString());
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "__NSCFBoolean"))
+ if (class_name == "__NSCFBoolean")
return ObjCBooleanSummaryProvider(valobj, stream, options);
- if (!strcmp(class_name, "NSNumber") || !strcmp(class_name, "__NSCFNumber")) {
+ if (class_name == "NSDecimalNumber")
+ return NSDecimalNumberSummaryProvider(valobj, stream, options);
+
+ if (class_name == "NSNumber" || class_name == "__NSCFNumber") {
uint64_t value = 0;
uint64_t i_bits = 0;
if (descriptor->GetTaggedPointerInfo(&i_bits, &value)) {
@@ -626,6 +628,55 @@ bool lldb_private::formatters::NSNumberSummaryProvider(
return false;
}
+bool lldb_private::formatters::NSDecimalNumberSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ Status error;
+ int8_t exponent = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size, 1, 0, error);
+ if (error.Fail())
+ return false;
+
+ uint8_t length_and_negative = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size + 1, 1, 0, error);
+ if (error.Fail())
+ return false;
+
+ // Fifth bit marks negativity.
+ const bool is_negative = (length_and_negative >> 4) & 1;
+
+ // Zero length and negative means NaN.
+ uint8_t length = length_and_negative & 0xf;
+ const bool is_nan = is_negative && (length == 0);
+
+ if (is_nan) {
+ stream.Printf("NaN");
+ return true;
+ }
+
+ if (length == 0) {
+ stream.Printf("0");
+ return true;
+ }
+
+ uint64_t mantissa = process_sp->ReadUnsignedIntegerFromMemory(
+ valobj_addr + ptr_size + 4, 8, 0, error);
+ if (error.Fail())
+ return false;
+
+ if (is_negative)
+ stream.Printf("-");
+
+ stream.Printf("%" PRIu64 " x 10^%" PRIi8, mantissa, exponent);
+ return true;
+}
+
bool lldb_private::formatters::NSURLSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
ProcessSP process_sp = valobj.GetProcessSP();
@@ -766,9 +817,9 @@ bool lldb_private::formatters::NSDateSummaryProvider(
stream.Printf("0001-12-30 00:00:00 +0000");
return true;
}
- // this snippet of code assumes that time_t == seconds since Jan-1-1970
- // this is generally true and POSIXly happy, but might break if a library
- // vendor decides to get creative
+ // this snippet of code assumes that time_t == seconds since Jan-1-1970 this
+ // is generally true and POSIXly happy, but might break if a library vendor
+ // decides to get creative
time_t epoch = GetOSXEpoch();
epoch = epoch + (time_t)date_value;
tm *tm_date = gmtime(&epoch);
@@ -871,28 +922,34 @@ bool lldb_private::formatters::NSDataSummaryProvider(
uint64_t value = 0;
- const char *class_name = descriptor->GetClassName().GetCString();
+ llvm::StringRef class_name = descriptor->GetClassName().GetCString();
- if (!class_name || !*class_name)
+ if (class_name.empty())
return false;
- if (!strcmp(class_name, "NSConcreteData") ||
- !strcmp(class_name, "NSConcreteMutableData") ||
- !strcmp(class_name, "__NSCFData")) {
- uint32_t offset = (is_64bit ? 16 : 8);
+ bool isNSConcreteData = class_name == "NSConcreteData";
+ bool isNSConcreteMutableData = class_name == "NSConcreteMutableData";
+ bool isNSCFData = class_name == "__NSCFData";
+ if (isNSConcreteData || isNSConcreteMutableData || isNSCFData) {
+ uint32_t offset;
+ if (isNSConcreteData)
+ offset = is_64bit ? 8 : 4;
+ else
+ offset = is_64bit ? 16 : 8;
+
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(
valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
if (error.Fail())
return false;
- } else if (!strcmp(class_name, "_NSInlineData")) {
+ } else if (class_name == "_NSInlineData") {
uint32_t offset = (is_64bit ? 8 : 4);
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2,
0, error);
if (error.Fail())
return false;
- } else if (!strcmp(class_name, "_NSZeroData")) {
+ } else if (class_name == "_NSZeroData") {
value = 0;
} else
return false;
diff --git a/source/Plugins/Language/ObjC/Cocoa.h b/source/Plugins/Language/ObjC/Cocoa.h
index 10ff3bce3b98..0f2ca5496302 100644
--- a/source/Plugins/Language/ObjC/Cocoa.h
+++ b/source/Plugins/Language/ObjC/Cocoa.h
@@ -32,6 +32,9 @@ bool NSDataSummaryProvider(ValueObject &valobj, Stream &stream,
bool NSNumberSummaryProvider(ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options);
+bool NSDecimalNumberSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+
bool NSNotificationSummaryProvider(ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options);
diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp
index c564aa1a8571..5be051b46bd6 100644
--- a/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -396,6 +396,8 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
static const ConstString g_DictionaryMImmutable("__NSDictionaryM_Immutable");
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
+ static const ConstString g_Dictionary0("__NSDictionary0");
+ static const ConstString g_DictionaryCF("__NSCFDictionary");
if (class_name.IsEmpty())
return false;
@@ -407,7 +409,8 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
if (error.Fail())
return false;
value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
- } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy) {
+ } else if (class_name == g_DictionaryM || class_name == g_DictionaryMLegacy ||
+ class_name == g_DictionaryCF) {
AppleObjCRuntime *apple_runtime =
llvm::dyn_cast_or_null<AppleObjCRuntime>(runtime);
Status error;
@@ -423,17 +426,9 @@ bool lldb_private::formatters::NSDictionarySummaryProvider(
return false;
} else if (class_name == g_Dictionary1) {
value = 1;
+ } else if (class_name == g_Dictionary0) {
+ value = 0;
}
- /*else if (!strcmp(class_name,"__NSCFDictionary"))
- {
- Status error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ?
- 20 : 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x0f1f000000000000UL;
- }*/
else {
auto &map(NSDictionary_Additionals::GetAdditionalSummaries());
for (auto &candidate : map) {
@@ -491,6 +486,7 @@ lldb_private::formatters::NSDictionarySyntheticFrontEndCreator(
static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI");
static const ConstString g_DictionaryImmutable("__NSDictionaryM_Immutable");
static const ConstString g_DictionaryMLegacy("__NSDictionaryM_Legacy");
+ static const ConstString g_Dictionary0("__NSDictionary0");
if (class_name.IsEmpty())
return nullptr;
@@ -673,11 +669,7 @@ lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
GetIndexOfChildWithName(const ConstString &name) {
static const ConstString g_zero("[0]");
-
- if (name == g_zero)
- return 0;
-
- return UINT32_MAX;
+ return name == g_zero ? 0 : UINT32_MAX;
}
size_t lldb_private::formatters::NSDictionary1SyntheticFrontEnd::
diff --git a/source/Plugins/Language/ObjC/NSError.cpp b/source/Plugins/Language/ObjC/NSError.cpp
index 4365a12b54e1..77721e2db326 100644
--- a/source/Plugins/Language/ObjC/NSError.cpp
+++ b/source/Plugins/Language/ObjC/NSError.cpp
@@ -177,12 +177,11 @@ public:
private:
// the child here can be "real" (i.e. an actual child of the root) or
- // synthetized from raw memory
- // if the former, I need to store a plain pointer to it - or else a loop of
- // references will cause this entire hierarchy of values to leak
- // if the latter, then I need to store a SharedPointer to it - so that it only
- // goes away when everyone else in the cluster goes away
- // oh joy!
+ // synthetized from raw memory if the former, I need to store a plain pointer
+ // to it - or else a loop of references will cause this entire hierarchy of
+ // values to leak if the latter, then I need to store a SharedPointer to it -
+ // so that it only goes away when everyone else in the cluster goes away oh
+ // joy!
ValueObject *m_child_ptr;
ValueObjectSP m_child_sp;
};
diff --git a/source/Plugins/Language/ObjC/NSException.cpp b/source/Plugins/Language/ObjC/NSException.cpp
index 1da4f6de19a0..c6970efae4d3 100644
--- a/source/Plugins/Language/ObjC/NSException.cpp
+++ b/source/Plugins/Language/ObjC/NSException.cpp
@@ -171,12 +171,11 @@ public:
private:
// the child here can be "real" (i.e. an actual child of the root) or
- // synthetized from raw memory
- // if the former, I need to store a plain pointer to it - or else a loop of
- // references will cause this entire hierarchy of values to leak
- // if the latter, then I need to store a SharedPointer to it - so that it only
- // goes away when everyone else in the cluster goes away
- // oh joy!
+ // synthetized from raw memory if the former, I need to store a plain pointer
+ // to it - or else a loop of references will cause this entire hierarchy of
+ // values to leak if the latter, then I need to store a SharedPointer to it -
+ // so that it only goes away when everyone else in the cluster goes away oh
+ // joy!
ValueObject *m_child_ptr;
ValueObjectSP m_child_sp;
};
diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp
index fa2483ecc094..2da4bc034f32 100644
--- a/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/source/Plugins/Language/ObjC/NSSet.cpp
@@ -269,7 +269,8 @@ bool lldb_private::formatters::NSSetSummaryProvider(
if (!class_name || !*class_name)
return false;
- if (!strcmp(class_name, "__NSSetI")) {
+ if (!strcmp(class_name, "__NSSetI") ||
+ !strcmp(class_name, "__NSOrderedSetI")) {
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
ptr_size, 0, error);
@@ -289,32 +290,7 @@ bool lldb_private::formatters::NSSetSummaryProvider(
}
if (error.Fail())
return false;
- }
- /*else if (!strcmp(class_name,"__NSCFSet"))
- {
- Status error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ?
- 20 : 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x1fff000000000000UL;
- }
- else if (!strcmp(class_name,"NSCountedSet"))
- {
- Status error;
- value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size,
- ptr_size, 0, error);
- if (error.Fail())
- return false;
- value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 :
- 12), 4, 0, error);
- if (error.Fail())
- return false;
- if (is_64bit)
- value &= ~0x1fff000000000000UL;
- }*/
- else {
+ } else {
auto &map(NSSet_Additionals::GetAdditionalSummaries());
auto iter = map.find(class_name_cs), end = map.end();
if (iter != end)
@@ -371,7 +347,8 @@ lldb_private::formatters::NSSetSyntheticFrontEndCreator(
if (!class_name || !*class_name)
return nullptr;
- if (!strcmp(class_name, "__NSSetI")) {
+ if (!strcmp(class_name, "__NSSetI") ||
+ !strcmp(class_name, "__NSOrderedSetI")) {
return (new NSSetISyntheticFrontEnd(valobj_sp));
} else if (!strcmp(class_name, "__NSSetM")) {
AppleObjCRuntime *apple_runtime =
diff --git a/source/Plugins/Language/ObjC/NSString.cpp b/source/Plugins/Language/ObjC/NSString.cpp
index 3b4edf68e063..0b12edb53d7a 100644
--- a/source/Plugins/Language/ObjC/NSString.cpp
+++ b/source/Plugins/Language/ObjC/NSString.cpp
@@ -256,8 +256,7 @@ bool lldb_private::formatters::NSStringSummaryProvider(
uint64_t location = valobj_addr + 2 * ptr_size;
if (!has_explicit_length) {
// in this kind of string, the byte before the string content is a length
- // byte
- // so let's try and use it to handle the embedded NUL case
+ // byte so let's try and use it to handle the embedded NUL case
Status error;
explicit_length =
process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
@@ -368,9 +367,7 @@ bool lldb_private::formatters::NSTaggedString_SummaryProvider(
}
// this is a fairly ugly trick - pretend that the numeric value is actually a
- // char*
- // this works under a few assumptions:
- // little endian architecture
+ // char* this works under a few assumptions: little endian architecture
// sizeof(uint64_t) > g_MaxNonBitmaskedLen
if (len_bits <= g_MaxNonBitmaskedLen) {
stream.Printf("%s", prefix.c_str());
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index ea2eec7b33b7..47874b3be8fd 100644
--- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -90,9 +90,8 @@ bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
if (name.empty())
return IsValid(strict);
- // If "strict" is true. then the method must be specified with a
- // '+' or '-' at the beginning. If "strict" is false, then the '+'
- // or '-' can be omitted
+ // If "strict" is true. then the method must be specified with a '+' or '-'
+ // at the beginning. If "strict" is false, then the '+' or '-' can be omitted
bool valid_prefix = false;
if (name.size() > 1 && (name[0] == '+' || name[0] == '-')) {
@@ -108,7 +107,7 @@ bool ObjCLanguage::MethodName::SetName(llvm::StringRef name, bool strict) {
if (valid_prefix) {
int name_len = name.size();
- // Objective C methods must have at least:
+ // Objective-C methods must have at least:
// "-[" or "+[" prefix
// One character for a class name
// One character for the space between the class name
@@ -134,8 +133,8 @@ const ConstString &ObjCLanguage::MethodName::GetClassName() {
if (paren_pos) {
m_class.SetCStringWithLength(class_start, paren_pos - class_start);
} else {
- // No '(' was found in the full name, we can definitively say
- // that our category was valid (and empty).
+ // No '(' was found in the full name, we can definitively say that our
+ // category was valid (and empty).
m_category_is_valid = true;
const char *space_pos = strchr(full, ' ');
if (space_pos) {
@@ -164,8 +163,8 @@ const ConstString &ObjCLanguage::MethodName::GetClassNameWithCategory() {
// contain a '(', then we can also fill in the m_class
if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) {
m_class = m_class_category;
- // No '(' was found in the full name, we can definitively say
- // that our category was valid (and empty).
+ // No '(' was found in the full name, we can definitively say that
+ // our category was valid (and empty).
m_category_is_valid = true;
}
}
@@ -764,6 +763,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
AddCXXSummary(
objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider,
"NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp,
+ lldb_private::formatters::NSNumberSummaryProvider,
+ "NSDecimalNumber summary provider",
+ ConstString("NSDecimalNumber"), appkit_flags);
AddCXXSummary(objc_category_sp,
lldb_private::formatters::NSURLSummaryProvider,
@@ -796,8 +799,8 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider,
"NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
- // CFAbsoluteTime is actually a double rather than a pointer to an object
- // we do not care about the numeric value, since it is probably meaningless to
+ // CFAbsoluteTime is actually a double rather than a pointer to an object we
+ // do not care about the numeric value, since it is probably meaningless to
// users
appkit_flags.SetDontShowValue(true);
AddCXXSummary(objc_category_sp,
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index e5a459dfe861..fc661bbbf2c9 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -83,26 +83,30 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(
// We are a C++ class, that's good. Get the class name and look it
// up:
const char *class_name = name + strlen(vtable_demangled_prefix);
+ // We know the class name is absolute, so tell FindTypes that by
+ // prefixing it with the root namespace:
+ std::string lookup_name("::");
+ lookup_name.append(class_name);
+
type_info.SetName(class_name);
const bool exact_match = true;
TypeList class_types;
uint32_t num_matches = 0;
- // First look in the module that the vtable symbol came from
- // and look for a single exact match.
+ // First look in the module that the vtable symbol came from and
+ // look for a single exact match.
llvm::DenseSet<SymbolFile *> searched_symbol_files;
if (sc.module_sp) {
num_matches = sc.module_sp->FindTypes(
- sc, ConstString(class_name), exact_match, 1,
+ sc, ConstString(lookup_name), exact_match, 1,
searched_symbol_files, class_types);
}
- // If we didn't find a symbol, then move on to the entire
- // module list in the target and get as many unique matches
- // as possible
+ // If we didn't find a symbol, then move on to the entire module
+ // list in the target and get as many unique matches as possible
if (num_matches == 0) {
num_matches = target.GetImages().FindTypes(
- sc, ConstString(class_name), exact_match, UINT32_MAX,
+ sc, ConstString(lookup_name), exact_match, UINT32_MAX,
searched_symbol_files, class_types);
}
@@ -187,15 +191,12 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
TypeAndOrName &class_type_or_name, Address &dynamic_address,
Value::ValueType &value_type) {
// For Itanium, if the type has a vtable pointer in the object, it will be at
- // offset 0
- // in the object. That will point to the "address point" within the vtable
- // (not the beginning of the
- // vtable.) We can then look up the symbol containing this "address point"
- // and that symbol's name
- // demangled will contain the full class name.
- // The second pointer above the "address point" is the "offset_to_top". We'll
- // use that to get the
- // start of the value object which holds the dynamic type.
+ // offset 0 in the object. That will point to the "address point" within the
+ // vtable (not the beginning of the vtable.) We can then look up the symbol
+ // containing this "address point" and that symbol's name demangled will
+ // contain the full class name. The second pointer above the "address point"
+ // is the "offset_to_top". We'll use that to get the start of the value
+ // object which holds the dynamic type.
//
class_type_or_name.Clear();
@@ -230,17 +231,15 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
if (class_type_or_name) {
TypeSP type_sp = class_type_or_name.GetTypeSP();
- // There can only be one type with a given name,
- // so we've just found duplicate definitions, and this
- // one will do as well as any other.
- // We don't consider something to have a dynamic type if
- // it is the same as the static type. So compare against
- // the value we were handed.
+ // There can only be one type with a given name, so we've just found
+ // duplicate definitions, and this one will do as well as any other. We
+ // don't consider something to have a dynamic type if it is the same as
+ // the static type. So compare against the value we were handed.
if (type_sp) {
if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(),
type_sp->GetForwardCompilerType())) {
- // The dynamic type we found was the same type,
- // so we don't have a dynamic type here...
+ // The dynamic type we found was the same type, so we don't have a
+ // dynamic type here...
return false;
}
@@ -257,8 +256,8 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
if (offset_to_top == INT64_MIN)
return false;
- // So the dynamic type is a value that starts at offset_to_top
- // above the original address.
+ // So the dynamic type is a value that starts at offset_to_top above
+ // the original address.
lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(
dynamic_addr, dynamic_address)) {
@@ -280,10 +279,9 @@ TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType(
TypeAndOrName ret(type_and_or_name);
if (type_and_or_name.HasType()) {
// The type will always be the type of the dynamic object. If our parent's
- // type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If
- // a reference, then the original type
- // should be okay...
+ // type was a pointer, then our type should be a pointer to the type of the
+ // dynamic object. If a reference, then the original type should be
+ // okay...
CompilerType orig_type = type_and_or_name.GetCompilerType();
CompilerType corrected_type = orig_type;
if (static_type_flags.AllSet(eTypeIsPointer))
@@ -368,8 +366,8 @@ protected:
// the actual Mangled class should be strict about this, but on the
// command line if you're copying mangled names out of 'nm' on Darwin,
- // they will come out with an extra underscore - be willing to strip
- // this on behalf of the user. This is the moral equivalent of the -_/-n
+ // they will come out with an extra underscore - be willing to strip this
+ // on behalf of the user. This is the moral equivalent of the -_/-n
// options to c++filt
auto name = entry.ref;
if (name.startswith("__Z"))
@@ -448,13 +446,12 @@ BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
BreakpointResolverSP ItaniumABILanguageRuntime::CreateExceptionResolver(
Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions) {
// One complication here is that most users DON'T want to stop at
- // __cxa_allocate_expression, but until we can do
- // anything better with predicting unwinding the expression parser does. So
- // we have two forms of the exception
- // breakpoints, one for expressions that leaves out __cxa_allocate_exception,
- // and one that includes it.
- // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint
- // in the runtime the former.
+ // __cxa_allocate_expression, but until we can do anything better with
+ // predicting unwinding the expression parser does. So we have two forms of
+ // the exception breakpoints, one for expressions that leaves out
+ // __cxa_allocate_exception, and one that includes it. The
+ // SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in
+ // the runtime the former.
static const char *g_catch_name = "__cxa_begin_catch";
static const char *g_throw_name1 = "__cxa_throw";
static const char *g_throw_name2 = "__cxa_rethrow";
@@ -517,8 +514,7 @@ void ItaniumABILanguageRuntime::SetExceptionBreakpoints() {
const bool for_expressions = true;
// For the exception breakpoints set by the Expression parser, we'll be a
- // little more aggressive and
- // stop at exception allocation as well.
+ // little more aggressive and stop at exception allocation as well.
if (m_cxx_exception_bp_sp) {
m_cxx_exception_bp_sp->SetEnabled(true);
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index ecb0b64f2346..edb29e735ca9 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -378,8 +378,7 @@ bool ClassDescriptorV2::Describe(
AppleObjCRuntime::ClassDescriptorSP metaclass(GetMetaclass());
// We don't care about the metaclass's superclass, or its class methods.
- // Its instance methods are
- // our class methods.
+ // Its instance methods are our class methods.
if (metaclass) {
metaclass->Describe(
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index eacc98a07193..fef42c78b24f 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -54,23 +54,20 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &str, ValueObject &valobj) {
CompilerType compiler_type(valobj.GetCompilerType());
bool is_signed;
// ObjC objects can only be pointers (or numbers that actually represents
- // pointers
- // but haven't been typecast, because reasons..)
+ // pointers but haven't been typecast, because reasons..)
if (!compiler_type.IsIntegerType(is_signed) && !compiler_type.IsPointerType())
return false;
- // Make the argument list: we pass one arg, the address of our pointer, to the
- // print function.
+ // Make the argument list: we pass one arg, the address of our pointer, to
+ // the print function.
Value val;
if (!valobj.ResolveValue(val.GetScalar()))
return false;
// Value Objects may not have a process in their ExecutionContextRef. But we
- // need to have one
- // in the ref we pass down to eventually call description. Get it from the
- // target if it isn't
- // present.
+ // need to have one in the ref we pass down to eventually call description.
+ // Get it from the target if it isn't present.
ExecutionContext exe_ctx;
if (valobj.GetProcessSP()) {
exe_ctx = ExecutionContext(valobj.GetExecutionContextRef());
@@ -257,10 +254,9 @@ AppleObjCRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
TypeAndOrName ret(type_and_or_name);
if (type_and_or_name.HasType()) {
// The type will always be the type of the dynamic object. If our parent's
- // type was a pointer,
- // then our type should be a pointer to the type of the dynamic object. If
- // a reference, then the original type
- // should be okay...
+ // type was a pointer, then our type should be a pointer to the type of the
+ // dynamic object. If a reference, then the original type should be
+ // okay...
CompilerType orig_type = type_and_or_name.GetCompilerType();
CompilerType corrected_type = orig_type;
if (static_type_flags.AllSet(eTypeIsPointer))
@@ -297,16 +293,14 @@ bool AppleObjCRuntime::AppleIsModuleObjCLibrary(const ModuleSP &module_sp) {
uint32_t AppleObjCRuntime::GetFoundationVersion() {
if (!m_Foundation_major.hasValue()) {
const ModuleList &modules = m_process->GetTarget().GetImages();
- uint32_t major = UINT32_MAX;
for (uint32_t idx = 0; idx < modules.GetSize(); idx++) {
lldb::ModuleSP module_sp = modules.GetModuleAtIndex(idx);
if (!module_sp)
continue;
if (strcmp(module_sp->GetFileSpec().GetFilename().AsCString(""),
"Foundation") == 0) {
- module_sp->GetVersion(&major, 1);
- m_Foundation_major = major;
- return major;
+ m_Foundation_major = module_sp->GetVersion().getMajor();
+ return *m_Foundation_major;
}
}
return LLDB_INVALID_MODULE_VERSION;
@@ -325,8 +319,8 @@ bool AppleObjCRuntime::IsModuleObjCLibrary(const ModuleSP &module_sp) {
bool AppleObjCRuntime::ReadObjCLibrary(const ModuleSP &module_sp) {
// Maybe check here and if we have a handler already, and the UUID of this
- // module is the same as the one in the
- // current module, then we don't have to reread it?
+ // module is the same as the one in the current module, then we don't have to
+ // reread it?
m_objc_trampoline_handler_ap.reset(
new AppleObjCTrampolineHandler(m_process->shared_from_this(), module_sp));
if (m_objc_trampoline_handler_ap.get() != NULL) {
@@ -365,11 +359,9 @@ AppleObjCRuntime::GetObjCVersion(Process *process, ModuleSP &objc_module_sp) {
for (size_t i = 0; i < num_images; i++) {
ModuleSP module_sp = target_modules.GetModuleAtIndexUnlocked(i);
// One tricky bit here is that we might get called as part of the initial
- // module loading, but
- // before all the pre-run libraries get winnowed from the module list. So
- // there might actually
- // be an old and incorrect ObjC library sitting around in the list, and we
- // don't want to look at that.
+ // module loading, but before all the pre-run libraries get winnowed from
+ // the module list. So there might actually be an old and incorrect ObjC
+ // library sitting around in the list, and we don't want to look at that.
// That's why we call IsLoadedInTarget.
if (AppleIsModuleObjCLibrary(module_sp) &&
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 9cac499c0ff0..5001c0461b3b 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -42,8 +42,7 @@ AppleObjCRuntimeV1::AppleObjCRuntimeV1(Process *process)
m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS) {}
// for V1 runtime we just try to return a class name as that is the minimum
-// level of support
-// required for the data formatters to work
+// level of support required for the data formatters to work
bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
ValueObject &in_value, lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name, Address &address,
@@ -85,7 +84,7 @@ AppleObjCRuntimeV1::CreateInstance(Process *process,
void AppleObjCRuntimeV1::Initialize() {
PluginManager::RegisterPlugin(
- GetPluginNameStatic(), "Apple Objective C Language Runtime - Version 1",
+ GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 1",
CreateInstance);
}
@@ -284,6 +283,10 @@ bool AppleObjCRuntimeV1::ClassDescriptorV1::Describe(
return false;
}
+lldb::addr_t AppleObjCRuntimeV1::GetTaggedPointerObfuscator() {
+ return 0;
+}
+
lldb::addr_t AppleObjCRuntimeV1::GetISAHashTablePointer() {
if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
ModuleSP objc_module_sp(GetObjCModule());
@@ -383,8 +386,8 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
ObjCISA isa;
if (bucket_isa_count == 1) {
- // When we only have one entry in the bucket, the bucket data is
- // the "isa"
+ // When we only have one entry in the bucket, the bucket data
+ // is the "isa"
isa = bucket_data;
if (isa) {
if (!ISAIsCached(isa)) {
@@ -402,8 +405,7 @@ void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() {
}
} else {
// When we have more than one entry in the bucket, the bucket
- // data is a pointer
- // to an array of "isa" values
+ // data is a pointer to an array of "isa" values
addr_t isa_addr = bucket_data;
for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count;
++isa_idx, isa_addr += addr_size) {
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 3dddf1b094e1..52eec0f692fb 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -45,6 +45,8 @@ public:
}
}
+ lldb::addr_t GetTaggedPointerObfuscator();
+
class ClassDescriptorV1 : public ObjCLanguageRuntime::ClassDescriptor {
public:
ClassDescriptorV1(ValueObject &isa_pointer);
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index bdf79f7b82bd..d217ed3ff325 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -37,6 +37,7 @@
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -76,8 +77,7 @@ static constexpr std::chrono::seconds g_utility_function_timeout(2);
static const char *g_get_dynamic_class_info_name =
"__lldb_apple_objc_v2_get_dynamic_class_info";
// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will
-// need to revert to the code above...
+// will need to revert to the code above...
static const char *g_get_dynamic_class_info_body = R"(
extern "C"
@@ -161,8 +161,7 @@ __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr
static const char *g_get_shared_cache_class_info_name =
"__lldb_apple_objc_v2_get_shared_cache_class_info";
// Testing using the new C++11 raw string literals. If this breaks GCC then we
-// will
-// need to revert to the code above...
+// will need to revert to the code above...
static const char *g_get_shared_cache_class_info_body = R"(
extern "C"
@@ -385,7 +384,9 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
m_get_class_info_args_mutex(), m_get_shared_cache_class_info_code(),
m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS),
m_get_shared_cache_class_info_args_mutex(), m_decl_vendor_ap(),
- m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), m_hash_signature(),
+ m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS),
+ m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS),
+ m_hash_signature(),
m_has_object_getClass(false), m_loaded_objc_opt(false),
m_non_pointer_isa_cache_ap(
NonPointerISACache::CreateInstance(*this, objc_module_sp)),
@@ -406,10 +407,9 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
assert(m_process != NULL);
// The Runtime is attached to a particular process, you shouldn't pass in a
- // value from another process.
- // Note, however, the process might be NULL (e.g. if the value was made with
- // SBTarget::EvaluateExpression...)
- // in which case it is sufficient if the target's match:
+ // value from another process. Note, however, the process might be NULL (e.g.
+ // if the value was made with SBTarget::EvaluateExpression...) in which case
+ // it is sufficient if the target's match:
Process *process = in_value.GetProcessSP().get();
if (process)
@@ -422,8 +422,8 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
// Make sure we can have a dynamic value before starting...
if (CouldHaveDynamicValue(in_value)) {
- // First job, pull out the address at 0 offset from the object That will be
- // the ISA pointer.
+ // First job, pull out the address at 0 offset from the object That will
+ // be the ISA pointer.
ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(in_value));
if (objc_class_sp) {
const addr_t object_ptr = in_value.GetPointerValue();
@@ -682,7 +682,7 @@ protected:
if (!arg_str)
continue;
Status error;
- lldb::addr_t arg_addr = Args::StringToAddress(
+ lldb::addr_t arg_addr = OptionArgParser::ToAddress(
&exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error);
if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail())
continue;
@@ -771,7 +771,7 @@ public:
void AppleObjCRuntimeV2::Initialize() {
PluginManager::RegisterPlugin(
- GetPluginNameStatic(), "Apple Objective C Language Runtime - Version 2",
+ GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 2",
CreateInstance,
[](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
@@ -870,8 +870,8 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
const char *class_name = parent_ast_type.GetConstTypeName().AsCString();
if (class_name && class_name[0] && ivar_name && ivar_name[0]) {
//----------------------------------------------------------------------
- // Make the objective C V2 mangled name for the ivar offset from the
- // class name and ivar name
+ // Make the objective C V2 mangled name for the ivar offset from the class
+ // name and ivar name
//----------------------------------------------------------------------
std::string buffer("OBJC_IVAR_$_");
buffer.append(class_name);
@@ -880,8 +880,8 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
ConstString ivar_const_str(buffer.c_str());
//----------------------------------------------------------------------
- // Try to get the ivar offset address from the symbol table first using
- // the name we created above
+ // Try to get the ivar offset address from the symbol table first using the
+ // name we created above
//----------------------------------------------------------------------
SymbolContextList sc_list;
Target &target = m_process->GetTarget();
@@ -914,11 +914,9 @@ size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
}
// tagged pointers are special not-a-real-pointer values that contain both type
-// and value information
-// this routine attempts to check with as little computational effort as
-// possible whether something
-// could possibly be a tagged pointer - false positives are possible but false
-// negatives shouldn't
+// and value information this routine attempts to check with as little
+// computational effort as possible whether something could possibly be a
+// tagged pointer - false positives are possible but false negatives shouldn't
bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) {
if (!m_tagged_pointer_vendor_ap)
return false;
@@ -950,11 +948,11 @@ public:
Status err;
// This currently holds true for all platforms we support, but we might
- // need to change this to use get the actually byte size of "unsigned"
- // from the target AST...
+ // need to change this to use get the actually byte size of "unsigned" from
+ // the target AST...
const uint32_t unsigned_byte_size = sizeof(uint32_t);
- // Skip the prototype as we don't need it (const struct +NXMapTablePrototype
- // *prototype)
+ // Skip the prototype as we don't need it (const struct
+ // +NXMapTablePrototype *prototype)
bool success = true;
if (load_addr == LLDB_INVALID_ADDRESS)
@@ -988,8 +986,8 @@ public:
return success;
}
- // const_iterator mimics NXMapState and its code comes from NXInitMapState and
- // NXNextMapState.
+ // const_iterator mimics NXMapState and its code comes from NXInitMapState
+ // and NXNextMapState.
typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
friend class const_iterator;
@@ -1132,8 +1130,8 @@ bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate(
return false; // Failed to parse the header, no need to update anything
}
- // Check with out current signature and return true if the count,
- // number of buckets or the hash table address changes.
+ // Check with out current signature and return true if the count, number of
+ // buckets or the hash table address changes.
if (m_count == hash_table.GetCount() &&
m_num_buckets == hash_table.GetBucketCount() &&
m_buckets_ptr == hash_table.GetBucketDataPointer()) {
@@ -1167,9 +1165,9 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
}
return nullptr;
}
- // if we get an invalid VO (which might still happen when playing around
- // with pointers returned by the expression parser, don't consider this
- // a valid ObjC object)
+ // if we get an invalid VO (which might still happen when playing around with
+ // pointers returned by the expression parser, don't consider this a valid
+ // ObjC object)
if (valobj.GetCompilerType().IsValid()) {
addr_t isa_pointer = valobj.GetPointerValue();
@@ -1200,6 +1198,38 @@ AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
return objc_class_sp;
}
+lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() {
+ if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS)
+ return m_tagged_pointer_obfuscator;
+
+
+ Process *process = GetProcess();
+ ModuleSP objc_module_sp(GetObjCModule());
+
+ if (!objc_module_sp)
+ return LLDB_INVALID_ADDRESS;
+
+ static ConstString g_gdb_objc_obfuscator("objc_debug_taggedpointer_obfuscator");
+
+ const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
+ g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
+ if (symbol) {
+ lldb::addr_t g_gdb_obj_obfuscator_ptr =
+ symbol->GetLoadAddress(&process->GetTarget());
+
+ if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) {
+ Status error;
+ m_tagged_pointer_obfuscator = process->ReadPointerFromMemory(
+ g_gdb_obj_obfuscator_ptr, error);
+ }
+ }
+ // If we don't have a correct value at this point, there must be no obfuscation.
+ if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS)
+ m_tagged_pointer_obfuscator = 0;
+
+ return m_tagged_pointer_obfuscator;
+}
+
lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
Process *process = GetProcess();
@@ -1359,8 +1389,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
- // Only dump the runtime classes from the expression evaluation if the
- // log is verbose:
+ // Only dump the runtime classes from the expression evaluation if the log is
+ // verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
@@ -1440,7 +1470,8 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
// uint32_t hash;
// } __attribute__((__packed__));
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES));
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
+ bool should_log = log && log->GetVerbose();
uint32_t num_parsed = 0;
@@ -1450,15 +1481,15 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
ObjCISA isa = data.GetPointer(&offset);
if (isa == 0) {
- if (log)
+ if (should_log)
log->Printf(
"AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
continue;
}
- // Check if we already know about this ISA, if we do, the info will
- // never change, so we can just skip it.
+ // Check if we already know about this ISA, if we do, the info will never
+ // change, so we can just skip it.
if (ISAIsCached(isa)) {
- if (log)
+ if (should_log)
log->Printf("AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
", ignoring this class info",
isa);
@@ -1469,14 +1500,14 @@ uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
ClassDescriptorSP descriptor_sp(new ClassDescriptorV2(*this, isa, NULL));
AddClass(isa, descriptor_sp, name_hash);
num_parsed++;
- if (log)
+ if (should_log)
log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64
", hash=0x%8.8x, name=%s",
isa, name_hash,
descriptor_sp->GetClassName().AsCString("<unknown>"));
}
}
- if (log)
+ if (should_log)
log->Printf("AppleObjCRuntimeV2 parsed %" PRIu32 " class infos",
num_parsed);
return num_parsed;
@@ -1607,8 +1638,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr;
arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size;
- // Only dump the runtime classes from the expression evaluation if the
- // log is verbose:
+ // Only dump the runtime classes from the expression evaluation if the log is
+ // verbose:
Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES);
bool dump_log = type_log && type_log->GetVerbose();
@@ -1788,21 +1819,17 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
DescriptorMapUpdateResult dynamic_update_result =
UpdateISAToDescriptorMapDynamic(hash_table);
- // Now get the objc classes that are baked into the Objective C runtime
- // in the shared cache, but only once per process as this data never
- // changes
+ // Now get the objc classes that are baked into the Objective-C runtime in
+ // the shared cache, but only once per process as this data never changes
if (!m_loaded_objc_opt) {
// it is legitimately possible for the shared cache to be empty - in that
- // case, the dynamic hash table
- // will contain all the class information we need; the situation we're
- // trying to detect is one where
- // we aren't seeing class information from the runtime - in order to
- // detect that vs. just the shared cache
- // being empty or sparsely populated, we set an arbitrary (very low)
- // threshold for the number of classes
- // that we want to see in a "good" scenario - anything below that is
- // suspicious (Foundation alone has thousands
- // of classes)
+ // case, the dynamic hash table will contain all the class information we
+ // need; the situation we're trying to detect is one where we aren't
+ // seeing class information from the runtime - in order to detect that
+ // vs. just the shared cache being empty or sparsely populated, we set an
+ // arbitrary (very low) threshold for the number of classes that we want
+ // to see in a "good" scenario - anything below that is suspicious
+ // (Foundation alone has thousands of classes)
const uint32_t num_classes_to_warn_at = 500;
DescriptorMapUpdateResult shared_cache_update_result =
@@ -2089,8 +2116,8 @@ AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
if (error.Fail())
return new TaggedPointerVendorLegacy(runtime);
- // try to detect the "extended tagged pointer" variables - if any are missing,
- // use the non-extended vendor
+ // try to detect the "extended tagged pointer" variables - if any are
+ // missing, use the non-extended vendor
do {
auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(
process, ConstString("objc_debug_taggedpointer_ext_mask"),
@@ -2143,8 +2170,8 @@ AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
} while (false);
- // we might want to have some rules to outlaw these values (e.g if the table's
- // address is zero)
+ // we might want to have some rules to outlaw these values (e.g if the
+ // table's address is zero)
return new TaggedPointerVendorRuntimeAssisted(
runtime, objc_debug_taggedpointer_mask,
@@ -2217,7 +2244,9 @@ AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor(
return ObjCLanguageRuntime::ClassDescriptorSP();
}
}
- return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, ptr));
+
+ lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator();
+ return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated));
}
AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
@@ -2249,8 +2278,9 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
uint64_t data_payload;
+ uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
- if (!IsPossibleTaggedPointer(ptr))
+ if (!IsPossibleTaggedPointer(unobfuscated))
return ObjCLanguageRuntime::ClassDescriptorSP();
uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
@@ -2276,7 +2306,7 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
}
data_payload =
- (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >>
+ (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
m_objc_debug_taggedpointer_payload_rshift);
return ClassDescriptorSP(
@@ -2333,11 +2363,12 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
lldb::addr_t ptr) {
ClassDescriptorSP actual_class_descriptor_sp;
uint64_t data_payload;
+ uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
- if (!IsPossibleTaggedPointer(ptr))
+ if (!IsPossibleTaggedPointer(unobfuscated))
return ObjCLanguageRuntime::ClassDescriptorSP();
- if (!IsPossibleExtendedTaggedPointer(ptr))
+ if (!IsPossibleExtendedTaggedPointer(unobfuscated))
return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);
uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
@@ -2363,7 +2394,7 @@ AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
}
data_payload =
- (((uint64_t)ptr << m_objc_debug_taggedpointer_ext_payload_lshift) >>
+ (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >>
m_objc_debug_taggedpointer_ext_payload_rshift);
return ClassDescriptorSP(
@@ -2414,11 +2445,10 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
if ((isa & ~m_objc_debug_isa_class_mask) == 0)
return false;
- // If all of the indexed ISA variables are set, then its possible that
- // this ISA is indexed, and we should first try to get its value using
- // the index.
- // Note, we check these varaibles first as the ObjC runtime will set at
- // least one of their values to 0 if they aren't needed.
+ // If all of the indexed ISA variables are set, then its possible that this
+ // ISA is indexed, and we should first try to get its value using the index.
+ // Note, we check these varaibles first as the ObjC runtime will set at least
+ // one of their values to 0 if they aren't needed.
if (m_objc_debug_indexed_isa_magic_mask &&
m_objc_debug_indexed_isa_magic_value &&
m_objc_debug_indexed_isa_index_mask &&
@@ -2431,10 +2461,10 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
// Magic bits are correct, so try extract the index.
uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >>
m_objc_debug_indexed_isa_index_shift;
- // If the index is out of bounds of the length of the array then
- // check if the array has been updated. If that is the case then
- // we should try read the count again, and update the cache if the
- // count has been updated.
+ // If the index is out of bounds of the length of the array then check if
+ // the array has been updated. If that is the case then we should try
+ // read the count again, and update the cache if the count has been
+ // updated.
if (index > m_indexed_isa_cache.size()) {
if (log)
log->Printf("AOCRT::NPI (index = %" PRIu64
@@ -2459,9 +2489,9 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
(uint64_t)objc_indexed_classes_count);
if (objc_indexed_classes_count > m_indexed_isa_cache.size()) {
- // Read the class entries we don't have. We should just
- // read all of them instead of just the one we need as then
- // we can cache those we may need later.
+ // Read the class entries we don't have. We should just read all of
+ // them instead of just the one we need as then we can cache those we
+ // may need later.
auto num_new_classes =
objc_indexed_classes_count - m_indexed_isa_cache.size();
const uint32_t addr_size = process->GetAddressByteSize();
@@ -2504,8 +2534,8 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
return false;
}
- // Definately not an indexed ISA, so try to use a mask to extract
- // the pointer from the ISA.
+ // Definately not an indexed ISA, so try to use a mask to extract the pointer
+ // from the ISA.
if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
ret_isa = isa & m_objc_debug_isa_class_mask;
return (ret_isa != 0); // this is a pointer so 0 is not a valid value
@@ -2533,14 +2563,14 @@ bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
if (m_CFBoolean_values)
return true;
- static ConstString g_kCFBooleanFalse("kCFBooleanFalse");
- static ConstString g_kCFBooleanTrue("kCFBooleanTrue");
+ static ConstString g_kCFBooleanFalse("__kCFBooleanFalse");
+ static ConstString g_kCFBooleanTrue("__kCFBooleanTrue");
std::function<lldb::addr_t(ConstString)> get_symbol =
[this](ConstString sym) -> lldb::addr_t {
SymbolContextList sc_list;
if (GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
- g_kCFBooleanFalse, lldb::eSymbolTypeData, sc_list) == 1) {
+ sym, lldb::eSymbolTypeData, sc_list) == 1) {
SymbolContext sc;
sc_list.GetContextAtIndex(0, sc);
if (sc.symbol)
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 89e81d5b181e..487b67ca6271 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -94,6 +94,8 @@ public:
return m_tagged_pointer_vendor_ap.get();
}
+ lldb::addr_t GetTaggedPointerObfuscator();
+
void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
lldb::addr_t &cf_false) override;
@@ -330,6 +332,7 @@ private:
std::mutex m_get_shared_cache_class_info_args_mutex;
std::unique_ptr<DeclVendor> m_decl_vendor_ap;
+ lldb::addr_t m_tagged_pointer_obfuscator;
lldb::addr_t m_isa_hash_table_ptr;
HashTableSignature m_hash_signature;
bool m_has_object_getClass;
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index a6e9c0c16f16..c75fa71ba131 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -49,227 +49,237 @@ const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name =
const char *AppleObjCTrampolineHandler::
g_lookup_implementation_with_stret_function_code =
" \n\
-extern \"C\" \n\
-{ \n\
- extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
- extern void *class_getMethodImplementation_stret(void *objc_class, void *sel); \n\
- extern void * object_getClass (id object); \n\
- extern void * sel_getUid(char *name); \n\
- extern int printf(const char *format, ...); \n\
-} \n\
-extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\
- void *sel, \n\
- int is_stret, \n\
- int is_super, \n\
- int is_super2, \n\
- int is_fixup, \n\
- int is_fixed, \n\
- int debug) \n\
-{ \n\
- struct __lldb_imp_return_struct \n\
- { \n\
- void *class_addr; \n\
- void *sel_addr; \n\
- void *impl_addr; \n\
- }; \n\
- \n\
- struct __lldb_objc_class { \n\
- void *isa; \n\
- void *super_ptr; \n\
- }; \n\
- struct __lldb_objc_super { \n\
- void *reciever; \n\
- struct __lldb_objc_class *class_ptr; \n\
- }; \n\
- struct __lldb_msg_ref { \n\
- void *dont_know; \n\
- void *sel; \n\
- }; \n\
- \n\
- struct __lldb_imp_return_struct return_struct; \n\
- \n\
- if (debug) \n\
- printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\
- \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
- object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\
- if (is_super) \n\
- { \n\
- if (is_super2) \n\
- { \n\
- return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\
- } \n\
- else \n\
- { \n\
- return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\
- } \n\
- } \n\
- else \n\
- { \n\
- // This code seems a little funny, but has its reasons... \n\
- // The call to [object class] is here because if this is a class, and has not been called into \n\
- // yet, we need to do something to force the class to initialize itself. \n\
- // Then the call to object_getClass will actually return the correct class, either the class \n\
- // if object is a class instance, or the meta-class if it is a class pointer. \n\
- void *class_ptr = (void *) [(id) object class]; \n\
- return_struct.class_addr = (id) object_getClass((id) object); \n\
- if (debug) \n\
- { \n\
- if (class_ptr == object) \n\
- { \n\
- printf (\"Found a class object, need to use the meta class %p -> %p\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- else \n\
- { \n\
- printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- } \n\
- } \n\
- \n\
- if (is_fixup) \n\
- { \n\
- if (is_fixed) \n\
- { \n\
- return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
- } \n\
- else \n\
- { \n\
- char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
- return_struct.sel_addr = sel_getUid (sel_name); \n\
- if (debug) \n\
- printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\", \n\
- return_struct.sel_addr, sel_name); \n\
- } \n\
- } \n\
- else \n\
- { \n\
- return_struct.sel_addr = sel; \n\
- } \n\
- \n\
- if (is_stret) \n\
- { \n\
- return_struct.impl_addr = class_getMethodImplementation_stret (return_struct.class_addr, \n\
- return_struct.sel_addr); \n\
- } \n\
- else \n\
- { \n\
- return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\
- return_struct.sel_addr); \n\
- } \n\
- if (debug) \n\
- printf (\"\\n*** Returning implementation: %p.\\n\", return_struct.impl_addr); \n\
- \n\
- return return_struct.impl_addr; \n\
-} \n\
+extern \"C\" \n\
+{ \n\
+ extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
+ extern void *class_getMethodImplementation_stret(void *objc_class, \n\
+ void *sel); \n\
+ extern void * object_getClass (id object); \n\
+ extern void * sel_getUid(char *name); \n\
+ extern int printf(const char *format, ...); \n\
+} \n\
+extern \"C\" void * __lldb_objc_find_implementation_for_selector ( \n\
+ void *object, \n\
+ void *sel, \n\
+ int is_stret, \n\
+ int is_super, \n\
+ int is_super2, \n\
+ int is_fixup, \n\
+ int is_fixed, \n\
+ int debug) \n\
+{ \n\
+ struct __lldb_imp_return_struct \n\
+ { \n\
+ void *class_addr; \n\
+ void *sel_addr; \n\
+ void *impl_addr; \n\
+ }; \n\
+ \n\
+ struct __lldb_objc_class { \n\
+ void *isa; \n\
+ void *super_ptr; \n\
+ }; \n\
+ struct __lldb_objc_super { \n\
+ void *reciever; \n\
+ struct __lldb_objc_class *class_ptr; \n\
+ }; \n\
+ struct __lldb_msg_ref { \n\
+ void *dont_know; \n\
+ void *sel; \n\
+ }; \n\
+ \n\
+ struct __lldb_imp_return_struct return_struct; \n\
+ \n\
+ if (debug) \n\
+ printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \"\n\
+ \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
+ object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed);\n\
+ if (is_super) \n\
+ { \n\
+ if (is_super2) \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr;\n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr;\n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ // This code seems a little funny, but has its reasons... \n\
+ \n\
+ // The call to [object class] is here because if this is a \n\
+ // class, and has not been called into yet, we need to do \n\
+ // something to force the class to initialize itself. \n\
+ // Then the call to object_getClass will actually return the \n\
+ // correct class, either the class if object is a class \n\
+ // instance, or the meta-class if it is a class pointer. \n\
+ void *class_ptr = (void *) [(id) object class]; \n\
+ return_struct.class_addr = (id) object_getClass((id) object); \n\
+ if (debug) \n\
+ { \n\
+ if (class_ptr == object) \n\
+ { \n\
+ printf (\"Found a class object, need to use the meta class %p -> %p\\n\",\n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ else \n\
+ { \n\
+ printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ } \n\
+ } \n\
+ \n\
+ if (is_fixup) \n\
+ { \n\
+ if (is_fixed) \n\
+ { \n\
+ return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
+ } \n\
+ else \n\
+ { \n\
+ char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
+ return_struct.sel_addr = sel_getUid (sel_name); \n\
+ if (debug) \n\
+ printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\",\n\
+ return_struct.sel_addr, sel_name); \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.sel_addr = sel; \n\
+ } \n\
+ \n\
+ if (is_stret) \n\
+ { \n\
+ return_struct.impl_addr = \n\
+ class_getMethodImplementation_stret (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.impl_addr = \n\
+ class_getMethodImplementation (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ } \n\
+ if (debug) \n\
+ printf (\"\\n*** Returning implementation: %p.\\n\", \n\
+ return_struct.impl_addr); \n\
+ \n\
+ return return_struct.impl_addr; \n\
+} \n\
";
const char *
AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code =
" \n\
-extern \"C\" \n\
-{ \n\
- extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
- extern void * object_getClass (id object); \n\
- extern void * sel_getUid(char *name); \n\
- extern int printf(const char *format, ...); \n\
-} \n\
+extern \"C\" \n\
+{ \n\
+ extern void *class_getMethodImplementation(void *objc_class, void *sel); \n\
+ extern void * object_getClass (id object); \n\
+ extern void * sel_getUid(char *name); \n\
+ extern int printf(const char *format, ...); \n\
+} \n\
extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object, \n\
- void *sel, \n\
- int is_stret, \n\
- int is_super, \n\
- int is_super2, \n\
- int is_fixup, \n\
- int is_fixed, \n\
- int debug) \n\
-{ \n\
- struct __lldb_imp_return_struct \n\
- { \n\
- void *class_addr; \n\
- void *sel_addr; \n\
- void *impl_addr; \n\
- }; \n\
- \n\
- struct __lldb_objc_class { \n\
- void *isa; \n\
- void *super_ptr; \n\
- }; \n\
- struct __lldb_objc_super { \n\
- void *reciever; \n\
- struct __lldb_objc_class *class_ptr; \n\
- }; \n\
- struct __lldb_msg_ref { \n\
- void *dont_know; \n\
- void *sel; \n\
- }; \n\
- \n\
- struct __lldb_imp_return_struct return_struct; \n\
- \n\
- if (debug) \n\
+ void *sel, \n\
+ int is_stret, \n\
+ int is_super, \n\
+ int is_super2, \n\
+ int is_fixup, \n\
+ int is_fixed, \n\
+ int debug) \n\
+{ \n\
+ struct __lldb_imp_return_struct \n\
+ { \n\
+ void *class_addr; \n\
+ void *sel_addr; \n\
+ void *impl_addr; \n\
+ }; \n\
+ \n\
+ struct __lldb_objc_class { \n\
+ void *isa; \n\
+ void *super_ptr; \n\
+ }; \n\
+ struct __lldb_objc_super { \n\
+ void *reciever; \n\
+ struct __lldb_objc_class *class_ptr; \n\
+ }; \n\
+ struct __lldb_msg_ref { \n\
+ void *dont_know; \n\
+ void *sel; \n\
+ }; \n\
+ \n\
+ struct __lldb_imp_return_struct return_struct; \n\
+ \n\
+ if (debug) \n\
printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \" \n\
- \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
+ \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\", \n\
object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed); \n\
- if (is_super) \n\
- { \n\
- if (is_super2) \n\
- { \n\
+ if (is_super) \n\
+ { \n\
+ if (is_super2) \n\
+ { \n\
return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr; \n\
- } \n\
- else \n\
- { \n\
+ } \n\
+ else \n\
+ { \n\
return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr; \n\
- } \n\
- } \n\
- else \n\
- { \n\
- // This code seems a little funny, but has its reasons... \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ // This code seems a little funny, but has its reasons... \n\
// The call to [object class] is here because if this is a class, and has not been called into \n\
// yet, we need to do something to force the class to initialize itself. \n\
// Then the call to object_getClass will actually return the correct class, either the class \n\
// if object is a class instance, or the meta-class if it is a class pointer. \n\
- void *class_ptr = (void *) [(id) object class]; \n\
- return_struct.class_addr = (id) object_getClass((id) object); \n\
- if (debug) \n\
- { \n\
- if (class_ptr == object) \n\
- { \n\
+ void *class_ptr = (void *) [(id) object class]; \n\
+ return_struct.class_addr = (id) object_getClass((id) object); \n\
+ if (debug) \n\
+ { \n\
+ if (class_ptr == object) \n\
+ { \n\
printf (\"Found a class object, need to return the meta class %p -> %p\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- else \n\
- { \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ else \n\
+ { \n\
printf (\"[object class] returned: %p object_getClass: %p.\\n\", \n\
- class_ptr, return_struct.class_addr); \n\
- } \n\
- } \n\
- } \n\
- \n\
- if (is_fixup) \n\
- { \n\
- if (is_fixed) \n\
- { \n\
- return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
- } \n\
- else \n\
- { \n\
- char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
- return_struct.sel_addr = sel_getUid (sel_name); \n\
- if (debug) \n\
- printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\", \n\
- return_struct.sel_addr, sel_name); \n\
- } \n\
- } \n\
- else \n\
- { \n\
- return_struct.sel_addr = sel; \n\
- } \n\
- \n\
- return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr, \n\
- return_struct.sel_addr); \n\
- if (debug) \n\
- printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr); \n\
- \n\
- return return_struct.impl_addr; \n\
-} \n\
+ class_ptr, return_struct.class_addr); \n\
+ } \n\
+ } \n\
+ } \n\
+ \n\
+ if (is_fixup) \n\
+ { \n\
+ if (is_fixed) \n\
+ { \n\
+ return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel; \n\
+ } \n\
+ else \n\
+ { \n\
+ char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel; \n\
+ return_struct.sel_addr = sel_getUid (sel_name); \n\
+ if (debug) \n\
+ printf (\"\\n*** Got fixed up selector: %p for name %s.\\n\",\n\
+ return_struct.sel_addr, sel_name); \n\
+ } \n\
+ } \n\
+ else \n\
+ { \n\
+ return_struct.sel_addr = sel; \n\
+ } \n\
+ \n\
+ return_struct.impl_addr = \n\
+ class_getMethodImplementation (return_struct.class_addr, \n\
+ return_struct.sel_addr); \n\
+ if (debug) \n\
+ printf (\"\\n*** Returning implementation: 0x%p.\\n\", \n\
+ return_struct.impl_addr); \n\
+ \n\
+ return return_struct.impl_addr; \n\
+} \n\
";
AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(
@@ -328,12 +338,11 @@ void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
// uint32_t offset
// uint32_t flags
//
- // Where offset is either 0 - in which case it is unused, or
- // it is the offset of the vtable code from the beginning of the descriptor
- // record.
- // Below, we'll convert that into an absolute code address, since I don't want
- // to have
- // to compute it over and over.
+ // Where offset is either 0 - in which case it is unused, or it is
+ // the offset of the vtable code from the beginning of the
+ // descriptor record. Below, we'll convert that into an absolute
+ // code address, since I don't want to have to compute it over and
+ // over.
// Ingest the whole descriptor array:
const lldb::addr_t desc_ptr = m_header_addr + header_size;
@@ -370,10 +379,9 @@ void AppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion() {
offset = start_offset + descriptor_size;
}
- // Finally, a little bird told me that all the vtable code blocks are the same
- // size.
- // Let's compute the blocks and if they are all the same add the size to the
- // code end address:
+ // Finally, a little bird told me that all the vtable code blocks
+ // are the same size. Let's compute the blocks and if they are all
+ // the same add the size to the code end address:
lldb::addr_t code_size = 0;
bool all_the_same = true;
for (size_t i = 0; i < num_descriptors - 1; i++) {
@@ -548,9 +556,8 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines(
}
bool AppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions() {
- // The no argument version reads the start region from the value of the
- // gdb_regions_header, and
- // gets started from there.
+ // The no argument version reads the start region from the value of
+ // the gdb_regions_header, and gets started from there.
m_regions.clear();
if (!InitializeVTableSymbols())
@@ -718,13 +725,12 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler(
g_lookup_implementation_with_stret_function_code;
}
- // Look up the addresses for the objc dispatch functions and cache them. For
- // now I'm inspecting the symbol
- // names dynamically to figure out how to dispatch to them. If it becomes
- // more complicated than this we can
- // turn the g_dispatch_functions char * array into a template table, and
- // populate the DispatchFunction map
- // from there.
+ // Look up the addresses for the objc dispatch functions and cache
+ // them. For now I'm inspecting the symbol names dynamically to
+ // figure out how to dispatch to them. If it becomes more
+ // complicated than this we can turn the g_dispatch_functions char *
+ // array into a template table, and populate the DispatchFunction
+ // map from there.
for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++) {
ConstString name_const_str(g_dispatch_functions[i].name);
@@ -732,11 +738,11 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler(
m_objc_module_sp->FindFirstSymbolWithNameAndType(name_const_str,
eSymbolTypeCode);
if (msgSend_symbol && msgSend_symbol->ValueIsAddress()) {
- // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and
- // have the map be address->index.
- // Problem is we also need to lookup the dispatch function. For now we
- // could have a side table of stret & non-stret
- // dispatch functions. If that's as complex as it gets, we're fine.
+ // FIXME: Make g_dispatch_functions static table of
+ // DispatchFunctions, and have the map be address->index.
+ // Problem is we also need to lookup the dispatch function. For
+ // now we could have a side table of stret & non-stret dispatch
+ // functions. If that's as complex as it gets, we're fine.
lldb::addr_t sym_addr =
msgSend_symbol->GetAddressRef().GetOpcodeLoadAddress(target);
@@ -820,11 +826,11 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
diagnostics.Clear();
- // Now write down the argument values for this particular call. This looks
- // like it might be a race condition
- // if other threads were calling into here, but actually it isn't because we
- // allocate a new args structure for
- // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+ // Now write down the argument values for this particular call.
+ // This looks like it might be a race condition if other threads
+ // were calling into here, but actually it isn't because we allocate
+ // a new args structure for this call by passing args_addr =
+ // LLDB_INVALID_ADDRESS...
if (!impl_function_caller->WriteFunctionArguments(
exe_ctx, args_addr, dispatch_values, diagnostics)) {
@@ -847,9 +853,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
DispatchFunction this_dispatch;
bool found_it = false;
- // First step is to look and see if we are in one of the known ObjC dispatch
- // functions. We've already compiled
- // a table of same, so consult it.
+ // First step is to look and see if we are in one of the known ObjC
+ // dispatch functions. We've already compiled a table of same, so
+ // consult it.
MsgsendMap::iterator pos;
pos = m_msgSend_map.find(curr_pc);
@@ -879,8 +885,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
if (found_it) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- // We are decoding a method dispatch.
- // First job is to pull the arguments out:
+ // We are decoding a method dispatch. First job is to pull the
+ // arguments out:
lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
@@ -906,10 +912,10 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
int obj_index;
int sel_index;
- // If this is a struct return dispatch, then the first argument is the
- // return struct pointer, and the object is the second, and the selector is
- // the third.
- // Otherwise the object is the first and the selector the second.
+ // If this is a struct return dispatch, then the first argument is
+ // the return struct pointer, and the object is the second, and
+ // the selector is the third. Otherwise the object is the first
+ // and the selector the second.
if (this_dispatch.stret_return) {
obj_index = 1;
sel_index = 2;
@@ -938,29 +944,26 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
ExecutionContext exe_ctx(thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
- // isa_addr will store the class pointer that the method is being dispatched
- // to - so either the class
- // directly or the super class if this is one of the objc_msgSendSuper
- // flavors. That's mostly used to
- // look up the class/selector pair in our cache.
+ // isa_addr will store the class pointer that the method is being
+ // dispatched to - so either the class directly or the super class
+ // if this is one of the objc_msgSendSuper flavors. That's mostly
+ // used to look up the class/selector pair in our cache.
lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
lldb::addr_t sel_addr =
argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
- // Figure out the class this is being dispatched to and see if we've already
- // cached this method call,
- // If so we can push a run-to-address plan directly. Otherwise we have to
- // figure out where
- // the implementation lives.
+ // Figure out the class this is being dispatched to and see if
+ // we've already cached this method call, If so we can push a
+ // run-to-address plan directly. Otherwise we have to figure out
+ // where the implementation lives.
if (this_dispatch.is_super) {
if (this_dispatch.is_super2) {
- // In the objc_msgSendSuper2 case, we don't get the object directly, we
- // get a structure containing
- // the object and the class to which the super message is being sent.
- // So we need to dig the super
- // out of the class and use that.
+ // In the objc_msgSendSuper2 case, we don't get the object
+ // directly, we get a structure containing the object and the
+ // class to which the super message is being sent. So we need
+ // to dig the super out of the class and use that.
Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
super_value.GetScalar() += process->GetAddressByteSize();
@@ -984,11 +987,11 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
log->Printf("Failed to extract the class value from objc_super.");
}
} else {
- // In the objc_msgSendSuper case, we don't get the object directly, we
- // get a two element structure containing
- // the object and the super class to which the super message is being
- // sent. So the class we want is
- // the second element of this structure.
+ // In the objc_msgSendSuper case, we don't get the object
+ // directly, we get a two element structure containing the
+ // object and the super class to which the super message is
+ // being sent. So the class we want is the second element of
+ // this structure.
Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
super_value.GetScalar() += process->GetAddressByteSize();
@@ -1009,9 +1012,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
// making the object value a load address value and resolving it will get
// the pointer sized data pointed to by that value...
- // Note, it isn't a fatal error not to be able to get the address from the
- // object, since this might
- // be a "tagged pointer" which isn't a real object, but rather some word
+ // Note, it isn't a fatal error not to be able to get the
+ // address from the object, since this might be a "tagged
+ // pointer" which isn't a real object, but rather some word
// length encoded dingus.
Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
@@ -1126,9 +1129,9 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
flag_value.GetScalar() = 0; // FIXME - Set to 0 when debugging is done.
dispatch_values.PushValue(flag_value);
- // The step through code might have to fill in the cache, so it is not
- // safe to run only one thread.
- // So we override the stop_others value passed in to us here:
+ // The step through code might have to fill in the cache, so it
+ // is not safe to run only one thread. So we override the
+ // stop_others value passed in to us here:
const bool trampoline_stop_others = false;
ret_plan_sp.reset(new AppleThreadPlanStepThroughObjCTrampoline(
thread, this, dispatch_values, isa_addr, sel_addr,
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
index 316115b0dcb1..9bb1a4e0ee42 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -105,10 +105,9 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
return clang::QualType();
std::string name(ReadStructName(type));
- // We do not handle templated classes/structs at the moment.
- // If the name has a < in it, we are going to abandon this.
- // We're still obliged to parse it, so we just set a flag that
- // means "Don't actually build anything."
+ // We do not handle templated classes/structs at the moment. If the name has
+ // a < in it, we are going to abandon this. We're still obliged to parse it,
+ // so we just set a flag that means "Don't actually build anything."
const bool is_templated = name.find('<') != std::string::npos;
@@ -180,11 +179,9 @@ AppleObjCTypeEncodingParser::BuildArray(clang::ASTContext &ast_ctx,
// the runtime can emit these in the form of @"SomeType", giving more specifics
// this would be interesting for expression parser interop, but since we
-// actually try
-// to avoid exposing the ivar info to the expression evaluator, consume but
-// ignore the type info
-// and always return an 'id'; if anything, dynamic typing will resolve things
-// for us anyway
+// actually try to avoid exposing the ivar info to the expression evaluator,
+// consume but ignore the type info and always return an 'id'; if anything,
+// dynamic typing will resolve things for us anyway
clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
clang::ASTContext &ast_ctx, lldb_utility::StringLexer &type,
bool for_expression) {
@@ -197,24 +194,21 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
// We have to be careful here. We're used to seeing
// @"NSString"
// but in records it is possible that the string following an @ is the name
- // of the next field and @ means "id".
- // This is the case if anything unquoted except for "}", the end of the
- // type, or another name follows the quoted string.
+ // of the next field and @ means "id". This is the case if anything
+ // unquoted except for "}", the end of the type, or another name follows
+ // the quoted string.
//
// E.g.
// - @"NSString"@ means "id, followed by a field named NSString of type id"
- // - @"NSString"} means "a pointer to NSString and the end of the struct"
- // - @"NSString""nextField" means "a pointer to NSString and a field named
- // nextField"
- // - @"NSString" followed by the end of the string means "a pointer to
- // NSString"
+ // - @"NSString"} means "a pointer to NSString and the end of the struct" -
+ // @"NSString""nextField" means "a pointer to NSString and a field named
+ // nextField" - @"NSString" followed by the end of the string means "a
+ // pointer to NSString"
//
// As a result, the rule is: If we see @ followed by a quoted string, we
- // peek.
- // - If we see }, ), ], the end of the string, or a quote ("), the quoted
- // string is a class name.
- // - If we see anything else, the quoted string is a field name and we push
- // it back onto type.
+ // peek. - If we see }, ), ], the end of the string, or a quote ("), the
+ // quoted string is a class name. - If we see anything else, the quoted
+ // string is a field name and we push it back onto type.
name = ReadQuotedString(type);
@@ -260,9 +254,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
decl_vendor->FindDecls(ConstString(name), append, max_matches, decls);
// The user can forward-declare something that has no definition. The runtime
-// doesn't prohibit this at all.
-// This is a rare and very weird case. We keep this assert in debug builds so
-// we catch other weird cases.
+// doesn't prohibit this at all. This is a rare and very weird case. We keep
+// this assert in debug builds so we catch other weird cases.
#ifdef LLDB_CONFIGURATION_DEBUG
assert(num_types);
#else
@@ -315,8 +308,8 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
// if (!lldb_ctx)
// return clang::QualType();
// return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
- // which uses one of the constants if one is available, but we don't think all
- // this work is necessary.
+ // which uses one of the constants if one is available, but we don't think
+ // all this work is necessary.
case 'q':
return ast_ctx.LongLongTy;
case 'C':
@@ -364,11 +357,10 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
case '^': {
if (!for_expression && type.NextIf('?')) {
// if we are not supporting the concept of unknownAny, but what is being
- // created here is an unknownAny*, then
- // we can just get away with a void*
+ // created here is an unknownAny*, then we can just get away with a void*
// this is theoretically wrong (in the same sense as 'theoretically
- // nothing exists') but is way better than outright failure
- // in many practical cases
+ // nothing exists') but is way better than outright failure in many
+ // practical cases
return ast_ctx.VoidPtrTy;
} else {
clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index a295d1b4ce76..75b670739427 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -52,8 +52,8 @@ AppleThreadPlanStepThroughObjCTrampoline::
void AppleThreadPlanStepThroughObjCTrampoline::DidPush() {
// Setting up the memory space for the called function text might require
- // allocations,
- // i.e. a nested function call. This needs to be done as a PreResumeAction.
+ // allocations, i.e. a nested function call. This needs to be done as a
+ // PreResumeAction.
m_thread.GetProcess()->AddPreResumeAction(PreResumeInitializeFunctionCaller,
(void *)this);
}
@@ -110,8 +110,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::DoPlanExplainsStop(
Event *event_ptr) {
// If we get asked to explain the stop it will be because something went
// wrong (like the implementation for selector function crashed... We're
- // going
- // to figure out what to do about that, so we do explain the stop.
+ // going to figure out what to do about that, so we do explain the stop.
return true;
}
@@ -135,8 +134,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
}
// Second stage, if all went well with the function calling, then fetch the
- // target address, and
- // queue up a "run to that address" plan.
+ // target address, and queue up a "run to that address" plan.
if (!m_run_to_sp) {
Value target_addr_value;
ExecutionContext exc_ctx;
@@ -201,8 +199,8 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
return false;
}
-// The base class MischiefManaged does some cleanup - so you have to call it
-// in your MischiefManaged derived class.
+// The base class MischiefManaged does some cleanup - so you have to call it in
+// your MischiefManaged derived class.
bool AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged() {
if (IsPlanComplete())
return true;
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
index 654ac9abfcab..cbbc35f1c08a 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
@@ -38,14 +38,12 @@ using namespace lldb_renderscript;
// [``slang``](https://android.googlesource.com/platform/frameworks/compile/slang),
// the compiler frontend for RenderScript embeds an ARM specific triple in IR
-// that is shipped in the app, after
-// generating IR that has some assumptions that an ARM device is the target.
-// As the IR is then compiled on a device of unknown (at time the IR was
-// generated at least) architecture,
-// when calling RenderScript API function as part of debugger expressions, we
-// have to perform a fixup pass that
-// removes those assumptions right before the module is sent to be generated by
-// the llvm backend.
+// that is shipped in the app, after generating IR that has some assumptions
+// that an ARM device is the target. As the IR is then compiled on a device of
+// unknown (at time the IR was generated at least) architecture, when calling
+// RenderScript API function as part of debugger expressions, we have to
+// perform a fixup pass that removes those assumptions right before the module
+// is sent to be generated by the llvm backend.
namespace {
bool registerRSDefaultTargetOpts(clang::TargetOptions &proto,
@@ -107,10 +105,9 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
case llvm::Triple::ArchType::x86:
changed_module |= fixupX86FunctionCalls(module);
// For some reason this triple gets totally missed by the backend, and must
- // be set manually.
- // There a reference in bcc/Main.cpp about auto feature-detection being
- // removed from LLVM3.5, but I can't
- // see that discussion anywhere public.
+ // be set manually. There a reference in bcc/Main.cpp about auto feature-
+ // detection being removed from LLVM3.5, but I can't see that discussion
+ // anywhere public.
real_triple = "i686--linux-android";
break;
case llvm::Triple::ArchType::x86_64:
@@ -118,12 +115,12 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
break;
case llvm::Triple::ArchType::mipsel:
case llvm::Triple::ArchType::mips64el:
- // No actual IR fixup pass is needed on MIPS, but the datalayout
- // and targetmachine do need to be explicitly set.
+ // No actual IR fixup pass is needed on MIPS, but the datalayout and
+ // targetmachine do need to be explicitly set.
- // bcc explicitly compiles MIPS code to use the static relocation
- // model due to an issue with relocations in mclinker.
- // see libbcc/support/CompilerConfig.cpp for details
+ // bcc explicitly compiles MIPS code to use the static relocation model due
+ // to an issue with relocations in mclinker. see
+ // libbcc/support/CompilerConfig.cpp for details
reloc_model = llvm::Reloc::Static;
changed_module = true;
break;
@@ -146,8 +143,7 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
assert(target_machine &&
"failed to identify RenderScriptRuntime target machine");
// We've been using a triple and datalayout of some ARM variant all along,
- // so
- // we need to let the backend know that this is no longer the case.
+ // so we need to let the backend know that this is no longer the case.
if (log) {
log->Printf("%s - Changing RS target triple to '%s'", __FUNCTION__,
real_triple.str().c_str());
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index ad1083be0285..4eb15369aa1e 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -26,7 +26,6 @@
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -40,6 +39,7 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
@@ -312,7 +312,8 @@ bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
Status err;
- // find offset to arguments on the stack (+16 to skip over a0-a3 shadow space)
+ // find offset to arguments on the stack (+16 to skip over a0-a3 shadow
+ // space)
uint64_t sp = ctx.reg_ctx->GetSP() + 16;
for (size_t i = 0; i < num_args; ++i) {
@@ -447,12 +448,11 @@ bool IsRenderScriptScriptModule(ModuleSP module) {
}
bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) {
- // takes an argument of the form 'num[,num][,num]'.
- // Where 'coord_s' is a comma separated 1,2 or 3-dimensional coordinate
- // with the whitespace trimmed.
- // Missing coordinates are defaulted to zero.
- // If parsing of any elements fails the contents of &coord are undefined
- // and `false` is returned, `true` otherwise
+ // takes an argument of the form 'num[,num][,num]'. Where 'coord_s' is a
+ // comma separated 1,2 or 3-dimensional coordinate with the whitespace
+ // trimmed. Missing coordinates are defaulted to zero. If parsing of any
+ // elements fails the contents of &coord are undefined and `false` is
+ // returned, `true` otherwise
RegularExpression regex;
RegularExpression::Match regex_match(3);
@@ -593,7 +593,7 @@ struct RenderScriptRuntime::Element {
empirical_type<uint32_t> datum_size; // Size of a single Element with padding
empirical_type<uint32_t> padding; // Number of padding bytes
empirical_type<uint32_t>
- array_size; // Number of items in array, only needed for strucrs
+ array_size; // Number of items in array, only needed for structs
ConstString type_name; // Name of type, only needed for structs
static const ConstString &
@@ -633,8 +633,9 @@ struct RenderScriptRuntime::AllocationDetails {
// subelements, there may be more than one instance of the ElementHeader
// struct. With this first instance being the root element, and the other
// instances being the root's descendants. To identify which instances are an
- // ElementHeader's children, each struct is immediately followed by a sequence
- // of consecutive offsets to the start of its child structs. These offsets are
+ // ElementHeader's children, each struct is immediately followed by a
+ // sequence of consecutive offsets to the start of its child structs. These
+ // offsets are
// 4 bytes in size, and the 0 offset signifies no more children.
struct FileHeader {
uint8_t ident[4]; // ASCII 'RSAD' identifying the file
@@ -653,8 +654,8 @@ struct RenderScriptRuntime::AllocationDetails {
// Monotonically increasing from 1
static uint32_t ID;
- // Maps Allocation DataType enum and vector size to printable strings
- // using mapping from RenderScript numerical types summary documentation
+ // Maps Allocation DataType enum and vector size to printable strings using
+ // mapping from RenderScript numerical types summary documentation
static const char *RsDataTypeToString[][4];
// Maps Allocation DataKind enum to printable strings
@@ -844,11 +845,10 @@ RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter,
lldb_private::SymbolContext &context,
Address *, bool) {
// We need to have access to the list of reductions currently parsed, as
- // reduce names don't actually exist as
- // symbols in a module. They are only identifiable by parsing the .rs.info
- // packet, or finding the expand symbol. We
- // therefore need access to the list of parsed rs modules to properly resolve
- // reduction names.
+ // reduce names don't actually exist as symbols in a module. They are only
+ // identifiable by parsing the .rs.info packet, or finding the expand symbol.
+ // We therefore need access to the list of parsed rs modules to properly
+ // resolve reduction names.
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
ModuleSP module = context.module_sp;
@@ -967,8 +967,8 @@ Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback(
log->Printf("%s: Placed %sbreakpoint on %s", __FUNCTION__,
new_bp ? "new " : "", k.m_name.AsCString());
- // exit after placing the first breakpoint if we do not intend to stop
- // on all kernels making up this script group
+ // exit after placing the first breakpoint if we do not intend to stop on
+ // all kernels making up this script group
if (!m_stop_on_all)
break;
}
@@ -1684,8 +1684,8 @@ void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) {
const ModuleSP module = rsmodule_sp->m_module;
const FileSpec &file = module->GetPlatformFileSpec();
- // Iterate over all of the scripts that we currently know of.
- // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
+ // Iterate over all of the scripts that we currently know of. Note: We cant
+ // push or pop to m_scripts here or it may invalidate rs_script.
for (const auto &rs_script : m_scripts) {
// Extract the expected .so file path for this script.
std::string shared_lib;
@@ -1825,9 +1825,9 @@ const char *JITTemplate(ExpressionStrings e) {
// rsaTypeGetNativeData(Context*, Type*, void* typeData, size) Pack the
// data in the following way mHal.state.dimX; mHal.state.dimY;
- // mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement; into
- // typeData Need to specify 32 or 64 bit for uint_t since this differs
- // between devices
+ // mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement;
+ // into typeData Need to specify 32 or 64 bit for uint_t since this
+ // differs between devices
JIT_TEMPLATE_CONTEXT
"uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
", 0x%" PRIx64 ", data, 6); data[0]", // eExprTypeDimX
@@ -1882,10 +1882,10 @@ const char *JITTemplate(ExpressionStrings e) {
}
} // end of the anonymous namespace
-// JITs the RS runtime for the internal data pointer of an allocation. Is passed
-// x,y,z coordinates for the pointer to a specific element. Then sets the
-// data_ptr member in Allocation with the result. Returns true on success, false
-// otherwise
+// JITs the RS runtime for the internal data pointer of an allocation. Is
+// passed x,y,z coordinates for the pointer to a specific element. Then sets
+// the data_ptr member in Allocation with the result. Returns true on success,
+// false otherwise
bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc,
StackFrame *frame_ptr, uint32_t x,
uint32_t y, uint32_t z) {
@@ -1961,8 +1961,8 @@ bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc,
}
// JITs the RS runtime for information about the dimensions and type of an
-// allocation Then sets dimension and element_ptr members in Allocation with the
-// result. Returns true on success, false otherwise
+// allocation Then sets dimension and element_ptr members in Allocation with
+// the result. Returns true on success, false otherwise
bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc,
StackFrame *frame_ptr) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -2245,9 +2245,8 @@ bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc,
}
// JITs the RS runtime for information about the stride between rows in the
-// allocation. This is done to detect padding, since allocated memory is 16-byte
-// aligned.
-// Returns true on success, false otherwise
+// allocation. This is done to detect padding, since allocated memory is
+// 16-byte aligned. Returns true on success, false otherwise
bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc,
StackFrame *frame_ptr) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -2313,9 +2312,8 @@ bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc,
}
// Function attempts to set the type_name member of the paramaterised Element
-// object.
-// This string should be the name of the struct type the Element represents.
-// We need this string for pretty printing the Element to users.
+// object. This string should be the name of the struct type the Element
+// represents. We need this string for pretty printing the Element to users.
void RenderScriptRuntime::FindStructTypeName(Element &elem,
StackFrame *frame_ptr) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -2330,12 +2328,11 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
VariableList var_list;
for (auto module_sp : m_rsmodules)
module_sp->m_module->FindGlobalVariables(
- RegularExpression(llvm::StringRef(".")), true, UINT32_MAX, var_list);
+ RegularExpression(llvm::StringRef(".")), UINT32_MAX, var_list);
// Iterate over all the global variables looking for one with a matching type
- // to the Element.
- // We make the assumption a match exists since there needs to be a global
- // variable to reflect the struct type back into java host code.
+ // to the Element. We make the assumption a match exists since there needs to
+ // be a global variable to reflect the struct type back into java host code.
for (uint32_t i = 0; i < var_list.GetSize(); ++i) {
const VariableSP var_sp(var_list.GetVariableAtIndex(i));
if (!var_sp)
@@ -2347,15 +2344,14 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
// Find the number of variable fields.
// If it has no fields, or more fields than our Element, then it can't be
- // the struct we're looking for.
- // Don't check for equality since RS can add extra struct members for
- // padding.
+ // the struct we're looking for. Don't check for equality since RS can add
+ // extra struct members for padding.
size_t num_children = valobj_sp->GetNumChildren();
if (num_children > elem.children.size() || num_children == 0)
continue;
- // Iterate over children looking for members with matching field names.
- // If all the field names match, this is likely the struct we want.
+ // Iterate over children looking for members with matching field names. If
+ // all the field names match, this is likely the struct we want.
// TODO: This could be made more robust by also checking children data
// sizes, or array size
bool found = true;
@@ -2404,8 +2400,8 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
}
// Function sets the datum_size member of Element. Representing the size of a
-// single instance including padding.
-// Assumes the relevant allocation information has already been jitted.
+// single instance including padding. Assumes the relevant allocation
+// information has already been jitted.
void RenderScriptRuntime::SetElementSize(Element &elem) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
const Element::DataType type = *elem.type.get();
@@ -2446,9 +2442,9 @@ void RenderScriptRuntime::SetElementSize(Element &elem) {
data_size + padding);
}
-// Given an allocation, this function copies the allocation contents from device
-// into a buffer on the heap.
-// Returning a shared pointer to the buffer containing the data.
+// Given an allocation, this function copies the allocation contents from
+// device into a buffer on the heap. Returning a shared pointer to the buffer
+// containing the data.
std::shared_ptr<uint8_t>
RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc,
StackFrame *frame_ptr) {
@@ -2496,9 +2492,8 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc,
return buffer;
}
-// Function copies data from a binary file into an allocation.
-// There is a header at the start of the file, FileHeader, before the data
-// content itself.
+// Function copies data from a binary file into an allocation. There is a
+// header at the start of the file, FileHeader, before the data content itself.
// Information from this header is used to display warnings to the user about
// incompatibilities
bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
@@ -2630,7 +2625,8 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
// Calculate size of allocation data in file
size_t size = data_sp->GetByteSize() - file_header->hdr_size;
- // Check if the target allocation and file both have the same total data size.
+ // Check if the target allocation and file both have the same total data
+ // size.
const uint32_t alloc_size = *alloc->size.get();
if (alloc_size != size) {
strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64
@@ -2660,15 +2656,15 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
// Function takes as parameters a byte buffer, which will eventually be written
// to file as the element header, an offset into that buffer, and an Element
-// that will be saved into the buffer at the parametrised offset.
-// Return value is the new offset after writing the element into the buffer.
-// Elements are saved to the file as the ElementHeader struct followed by
-// offsets to the structs of all the element's children.
+// that will be saved into the buffer at the parametrised offset. Return value
+// is the new offset after writing the element into the buffer. Elements are
+// saved to the file as the ElementHeader struct followed by offsets to the
+// structs of all the element's children.
size_t RenderScriptRuntime::PopulateElementHeaders(
const std::shared_ptr<uint8_t> header_buffer, size_t offset,
const Element &elem) {
- // File struct for an element header with all the relevant details copied from
- // elem. We assume members are valid already.
+ // File struct for an element header with all the relevant details copied
+ // from elem. We assume members are valid already.
AllocationDetails::ElementHeader elem_header;
elem_header.type = *elem.type.get();
elem_header.kind = *elem.type_kind.get();
@@ -2678,9 +2674,8 @@ size_t RenderScriptRuntime::PopulateElementHeaders(
elem.array_size.isValid() ? *elem.array_size.get() : 0;
const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
- // Copy struct into buffer and advance offset
- // We assume that header_buffer has been checked for nullptr before this
- // method is called
+ // Copy struct into buffer and advance offset We assume that header_buffer
+ // has been checked for nullptr before this method is called
memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
offset += elem_header_size;
@@ -2721,8 +2716,8 @@ size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) {
return size;
}
-// Function copies allocation contents into a binary file. This file can then be
-// loaded later into a different allocation. There is a header, FileHeader,
+// Function copies allocation contents into a binary file. This file can then
+// be loaded later into a different allocation. There is a header, FileHeader,
// before the allocation data containing meta-data.
bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
const char *path,
@@ -2852,8 +2847,8 @@ bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
if (module_sp) {
for (const auto &rs_module : m_rsmodules) {
if (rs_module->m_module == module_sp) {
- // Check if the user has enabled automatically breaking on
- // all RS kernels.
+ // Check if the user has enabled automatically breaking on all RS
+ // kernels.
if (m_breakAllKernels)
BreakOnModuleKernels(rs_module);
@@ -2975,11 +2970,10 @@ bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines,
size_t n_lines) {
// The list of reduction kernels in the `.rs.info` symbol is of the form
// "signature - accumulatordatasize - reduction_name - initializer_name -
- // accumulator_name - combiner_name -
- // outconverter_name - halter_name"
- // Where a function is not explicitly named by the user, or is not generated
- // by the compiler, it is named "." so the
- // dash separated list should always be 8 items long
+ // accumulator_name - combiner_name - outconverter_name - halter_name" Where
+ // a function is not explicitly named by the user, or is not generated by the
+ // compiler, it is named "." so the dash separated list should always be 8
+ // items long
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
// Skip the exportReduceCount line
++lines;
@@ -3069,8 +3063,7 @@ bool RSModuleDescriptor::ParseExportVarCount(llvm::StringRef *lines,
}
// The .rs.info symbol in renderscript modules contains a string which needs to
-// be parsed.
-// The string is basic and is parsed on a line by line basis.
+// be parsed. The string is basic and is parsed on a line by line basis.
bool RSModuleDescriptor::ParseRSInfo() {
assert(m_module);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
@@ -3137,8 +3130,8 @@ bool RSModuleDescriptor::ParseRSInfo() {
const auto handler = rs_info_handler(key);
if (handler == -1)
continue;
- // getAsInteger returns `true` on an error condition - we're only interested
- // in numeric fields at the moment
+ // getAsInteger returns `true` on an error condition - we're only
+ // interested in numeric fields at the moment
uint64_t n_lines;
if (val.getAsInteger(10, n_lines)) {
LLDB_LOGV(log, "Failed to parse non-numeric '.rs.info' section {0}",
@@ -3213,9 +3206,8 @@ void RenderScriptRuntime::DumpContexts(Stream &strm) const {
std::map<addr_t, uint64_t> contextReferences;
- // Iterate over all of the currently discovered scripts.
- // Note: We cant push or pop from m_scripts inside this loop or it may
- // invalidate script.
+ // Iterate over all of the currently discovered scripts. Note: We cant push
+ // or pop from m_scripts inside this loop or it may invalidate script.
for (const auto &script : m_scripts) {
if (!script->context.isValid())
continue;
@@ -3393,15 +3385,15 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
if ((type == Element::RS_TYPE_NONE) &&
(alloc->element.children.size() > 0) &&
(alloc->element.type_name != Element::GetFallbackStructName())) {
- // Here we are dumping an Element of struct type.
- // This is done using expression evaluation with the name of the
- // struct type and pointer to element.
- // Don't print the name of the resulting expression, since this will
- // be '$[0-9]+'
+ // Here we are dumping an Element of struct type. This is done using
+ // expression evaluation with the name of the struct type and pointer
+ // to element. Don't print the name of the resulting expression,
+ // since this will be '$[0-9]+'
DumpValueObjectOptions expr_options;
expr_options.SetHideName(true);
- // Setup expression as derefrencing a pointer cast to element address.
+ // Setup expression as dereferencing a pointer cast to element
+ // address.
char expr_char_buffer[jit_max_expr_size];
int written =
snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
@@ -3435,9 +3427,9 @@ bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
return true;
}
-// Function recalculates all our cached information about allocations by jitting
-// the RS runtime regarding each allocation we know about. Returns true if all
-// allocations could be recomputed, false otherwise.
+// Function recalculates all our cached information about allocations by
+// jitting the RS runtime regarding each allocation we know about. Returns true
+// if all allocations could be recomputed, false otherwise.
bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm,
StackFrame *frame_ptr) {
bool success = true;
@@ -3601,8 +3593,8 @@ void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) {
}
}
-// Given the name of a kernel this function creates a breakpoint using our
-// own breakpoint resolver, and returns the Breakpoint shared pointer.
+// Given the name of a kernel this function creates a breakpoint using our own
+// breakpoint resolver, and returns the Breakpoint shared pointer.
BreakpointSP
RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) {
Log *log(
@@ -3743,8 +3735,8 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
log->Printf("%s - Found .expand function '%s'", __FUNCTION__,
func_name.GetCString());
- // Get values for variables in .expand frame that tell us the current kernel
- // invocation
+ // Get values for variables in .expand frame that tell us the current
+ // kernel invocation
uint64_t x, y, z;
bool found = GetFrameVarAsUnsigned(frame_sp, x_expr, x) &&
GetFrameVarAsUnsigned(frame_sp, y_expr, y) &&
@@ -3765,12 +3757,11 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
// Callback when a kernel breakpoint hits and we're looking for a specific
// coordinate. Baton parameter contains a pointer to the target coordinate we
-// want to break on.
-// Function then checks the .expand frame for the current coordinate and breaks
-// to user if it matches.
-// Parameter 'break_id' is the id of the Breakpoint which made the callback.
-// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
-// a single logical breakpoint can have multiple addresses.
+// want to break on. Function then checks the .expand frame for the current
+// coordinate and breaks to user if it matches. Parameter 'break_id' is the id
+// of the Breakpoint which made the callback. Parameter 'break_loc_id' is the
+// id for the BreakpointLocation which was hit, a single logical breakpoint can
+// have multiple addresses.
bool RenderScriptRuntime::KernelBreakpointHit(void *baton,
StoppointCallbackContext *ctx,
user_id_t break_id,
@@ -3845,12 +3836,10 @@ void RenderScriptRuntime::SetConditional(BreakpointSP bp, Stream &messages,
m_conditional_breaks[bp->GetID()] = std::unique_ptr<RSCoordinate>(baton);
}
-// Tries to set a breakpoint on the start of a kernel, resolved using the kernel
-// name. Argument 'coords', represents a three dimensional coordinate which can
-// be
-// used to specify a single kernel instance to break on. If this is set then we
-// add a callback
-// to the breakpoint.
+// Tries to set a breakpoint on the start of a kernel, resolved using the
+// kernel name. Argument 'coords', represents a three dimensional coordinate
+// which can be used to specify a single kernel instance to break on. If this
+// is set then we add a callback to the breakpoint.
bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target,
Stream &messages,
const char *name,
@@ -4076,7 +4065,7 @@ void RSModuleDescriptor::Dump(Stream &strm) const {
void RSGlobalDescriptor::Dump(Stream &strm) const {
strm.Indent(m_name.AsCString());
VariableList var_list;
- m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
+ m_module->m_module->FindGlobalVariables(m_name, nullptr, 1U, var_list);
if (var_list.GetSize() == 1) {
auto var = var_list.GetVariableAtIndex(0);
auto type = var->GetType();
@@ -4270,8 +4259,8 @@ public:
};
// Matching a comma separated list of known words is fairly
- // straightforward with PCRE, but we're
- // using ERE, so we end up with a little ugliness...
+ // straightforward with PCRE, but we're using ERE, so we end up with a
+ // little ugliness...
RegularExpression::Match match(/* max_matches */ 5);
RegularExpression match_type_list(
llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$"));
@@ -4661,7 +4650,7 @@ public:
switch (short_option) {
case 'f':
- m_outfile.SetFile(option_arg, true);
+ m_outfile.SetFile(option_arg, true, FileSpec::Style::native);
if (m_outfile.Exists()) {
m_outfile.Clear();
err.SetErrorStringWithFormat("file already exists: '%s'",
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
index fe4ae21a0c39..7786d686ad6a 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptScriptGroup.cpp
@@ -10,7 +10,6 @@
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -20,6 +19,7 @@
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
index 439d372fadeb..e1f8ea648414 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
@@ -46,18 +46,15 @@ bool isRSAPICall(llvm::Module &module, llvm::CallInst *call_inst) {
bool isRSLargeReturnCall(llvm::Module &module, llvm::CallInst *call_inst) {
// i686 and x86_64 returns for large vectors in the RenderScript API are not
- // handled as normal
- // register pairs, but as a hidden sret type. This is not reflected in the
- // debug info or mangled
- // symbol name, and the android ABI for x86 and x86_64, (as well as the
- // emulators) specifies there is
- // no AVX, so bcc generates an sret function because we cannot natively return
+ // handled as normal register pairs, but as a hidden sret type. This is not
+ // reflected in the debug info or mangled symbol name, and the android ABI
+ // for x86 and x86_64, (as well as the emulators) specifies there is no AVX,
+ // so bcc generates an sret function because we cannot natively return
// 256 bit vectors.
// This function simply checks whether a function has a > 128bit return type.
- // It is perhaps an
- // unreliable heuristic, and relies on bcc not generating AVX code, so if the
- // android ABI one day
- // provides for AVX, this function may go out of fashion.
+ // It is perhaps an unreliable heuristic, and relies on bcc not generating
+ // AVX code, so if the android ABI one day provides for AVX, this function
+ // may go out of fashion.
(void)module;
if (!call_inst || !call_inst->getCalledFunction())
return false;
@@ -88,12 +85,11 @@ bool isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst) {
llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
// on x86 StructReturn functions return a pointer to the return value, rather
- // than the return
- // value itself [ref](http://www.agner.org/optimize/calling_conventions.pdf
- // section 6).
- // We create a return type by getting the pointer type of the old return type,
- // and inserting a new
- // initial argument of pointer type of the original return type.
+ // than the return value itself
+ // [ref](http://www.agner.org/optimize/calling_conventions.pdf section 6). We
+ // create a return type by getting the pointer type of the old return type,
+ // and inserting a new initial argument of pointer type of the original
+ // return type.
Log *log(
GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_EXPRESSIONS));
@@ -112,8 +108,7 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
orig_type->param_end()};
// This may not work if the function is somehow declared void as llvm is
- // strongly typed
- // and represents void* with i8*
+ // strongly typed and represents void* with i8*
assert(!orig_type->getReturnType()->isVoidTy() &&
"Cannot add StructRet attribute to void function");
llvm::PointerType *return_type_ptr_type =
@@ -126,8 +121,8 @@ llvm::FunctionType *cloneToStructRetFnTy(llvm::CallInst *call_inst) {
if (log)
log->Printf("%s - return type pointer type for StructRet clone @ '0x%p':\n",
__FUNCTION__, (void *)return_type_ptr_type);
- // put the the sret pointer argument in place at the beginning of the argument
- // list.
+ // put the sret pointer argument in place at the beginning of the
+ // argument list.
params.emplace(params.begin(), return_type_ptr_type);
assert(params.size() == num_params + 1);
return llvm::FunctionType::get(return_type_ptr_type, params,
@@ -157,11 +152,9 @@ bool findRSCallSites(llvm::Module &module,
bool fixupX86StructRetCalls(llvm::Module &module) {
bool changed = false;
- // changing a basic block while iterating over it seems to have some undefined
- // behaviour
- // going on so we find all RS callsites first, then fix them up after
- // consuming
- // the iterator.
+ // changing a basic block while iterating over it seems to have some
+ // undefined behaviour going on so we find all RS callsites first, then fix
+ // them up after consuming the iterator.
std::set<llvm::CallInst *> rs_callsites;
if (!findRSCallSites(module, rs_callsites, isRSLargeReturnCall))
return false;
@@ -180,8 +173,7 @@ bool fixupX86StructRetCalls(llvm::Module &module) {
// Allocate enough space to store the return value of the original function
// we pass a pointer to this allocation as the StructRet param, and then
- // copy its
- // value into the lldb return value
+ // copy its value into the lldb return value
const llvm::DataLayout &DL = module.getDataLayout();
llvm::AllocaInst *return_value_alloc = new llvm::AllocaInst(
func->getReturnType(), DL.getAllocaAddrSpace(), "var_vector_return_alloc",
@@ -222,19 +214,15 @@ bool fixupX86StructRetCalls(llvm::Module &module) {
bool fixupRSAllocationStructByValCalls(llvm::Module &module) {
// On x86_64, calls to functions in the RS runtime that take an
- // `rs_allocation` type argument
- // are actually handled as by-ref params by bcc, but appear to be passed by
- // value by lldb (the callsite all use
- // `struct byval`).
- // On x86_64 Linux, struct arguments are transferred in registers if the
- // struct size is no bigger than
- // 128bits [ref](http://www.agner.org/optimize/calling_conventions.pdf)
- // section 7.1 "Passing and returning objects"
- // otherwise passed on the stack.
- // an object of type `rs_allocation` is actually 256bits, so should be passed
- // on the stack. However, code generated
- // by bcc actually treats formal params of type `rs_allocation` as
- // `rs_allocation *` so we need to convert the
+ // `rs_allocation` type argument are actually handled as by-ref params by
+ // bcc, but appear to be passed by value by lldb (the callsite all use
+ // `struct byval`). On x86_64 Linux, struct arguments are transferred in
+ // registers if the struct size is no bigger than 128bits
+ // [ref](http://www.agner.org/optimize/calling_conventions.pdf) section 7.1
+ // "Passing and returning objects" otherwise passed on the stack. an object
+ // of type `rs_allocation` is actually 256bits, so should be passed on the
+ // stack. However, code generated by bcc actually treats formal params of
+ // type `rs_allocation` as `rs_allocation *` so we need to convert the
// calling convention to pass by reference, and remove any hint of byval from
// formal parameters.
bool changed = false;
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index d7bef836d9d8..275f1fa2f70b 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -89,9 +89,9 @@ ObjectContainerBSDArchive::Object::Extract(const DataExtractor &data,
str.assign((const char *)data.GetData(&offset, 16), 16);
if (str.find("#1/") == 0) {
- // If the name is longer than 16 bytes, or contains an embedded space
- // then it will use this format where the length of the name is
- // here and the name characters are after this header.
+ // If the name is longer than 16 bytes, or contains an embedded space then
+ // it will use this format where the length of the name is here and the
+ // name characters are after this header.
ar_name_len = strtoul(str.c_str() + 3, &err, 10);
} else {
// Strip off any trailing spaces.
@@ -203,8 +203,8 @@ ObjectContainerBSDArchive::Archive::FindCachedArchive(
shared_ptr archive_sp;
Archive::Map &archive_map = Archive::GetArchiveCache();
Archive::Map::iterator pos = archive_map.find(file);
- // Don't cache a value for "archive_map.end()" below since we might
- // delete an archive entry...
+ // Don't cache a value for "archive_map.end()" below since we might delete an
+ // archive entry...
while (pos != archive_map.end() && pos->first == file) {
bool match = true;
if (arch.IsValid() &&
@@ -217,14 +217,13 @@ ObjectContainerBSDArchive::Archive::FindCachedArchive(
if (pos->second->GetModificationTime() == time) {
return pos->second;
} else {
- // We have a file at the same path with the same architecture
- // whose modification time doesn't match. It doesn't make sense
- // for us to continue to use this BSD archive since we cache only
- // the object info which consists of file time info and also the
- // file offset and file size of any contained objects. Since
- // this information is now out of date, we won't get the correct
- // information if we go and extract the file data, so we should
- // remove the old and outdated entry.
+ // We have a file at the same path with the same architecture whose
+ // modification time doesn't match. It doesn't make sense for us to
+ // continue to use this BSD archive since we cache only the object info
+ // which consists of file time info and also the file offset and file
+ // size of any contained objects. Since this information is now out of
+ // date, we won't get the correct information if we go and extract the
+ // file data, so we should remove the old and outdated entry.
archive_map.erase(pos);
pos = archive_map.find(file);
continue; // Continue to next iteration so we don't increment pos
@@ -295,9 +294,9 @@ ObjectContainer *ObjectContainerBSDArchive::CreateInstance(
return nullptr;
if (data_sp) {
- // We have data, which means this is the first 512 bytes of the file
- // Check to see if the magic bytes match and if they do, read the entire
- // table of contents for the archive and cache it
+ // We have data, which means this is the first 512 bytes of the file Check
+ // to see if the magic bytes match and if they do, read the entire table of
+ // contents for the archive and cache it
DataExtractor data;
data.SetData(data_sp, data_offset, length);
if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) {
@@ -389,8 +388,8 @@ bool ObjectContainerBSDArchive::ParseHeader() {
m_file, module_sp->GetArchitecture(),
module_sp->GetModificationTime(), m_offset, m_data);
}
- // Clear the m_data that contains the entire archive
- // data and let our m_archive_sp hold onto the data.
+ // Clear the m_data that contains the entire archive data and let our
+ // m_archive_sp hold onto the data.
m_data.Clear();
}
}
@@ -453,9 +452,9 @@ size_t ObjectContainerBSDArchive::GetModuleSpecifications(
lldb::offset_t data_offset, lldb::offset_t file_offset,
lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) {
- // We have data, which means this is the first 512 bytes of the file
- // Check to see if the magic bytes match and if they do, read the entire
- // table of contents for the archive and cache it
+ // We have data, which means this is the first 512 bytes of the file Check to
+ // see if the magic bytes match and if they do, read the entire table of
+ // contents for the archive and cache it
DataExtractor data;
data.SetData(data_sp, data_offset, data_sp->GetByteSize());
if (!file || !data_sp || !ObjectContainerBSDArchive::MagicBytesMatch(data))
@@ -505,8 +504,8 @@ size_t ObjectContainerBSDArchive::GetModuleSpecifications(
const size_t end_count = specs.GetSize();
size_t num_specs_added = end_count - initial_count;
if (set_archive_arch && num_specs_added > 0) {
- // The archive was created but we didn't have an architecture
- // so we need to set it
+ // The archive was created but we didn't have an architecture so we need to
+ // set it
for (size_t i = initial_count; i < end_count; ++i) {
ModuleSpec module_spec;
if (specs.GetModuleSpecAtIndex(i, module_spec)) {
diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
index 0266bbe27e7d..4c48d641829a 100644
--- a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
+++ b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
@@ -44,8 +44,8 @@ ObjectContainer *ObjectContainerUniversalMachO::CreateInstance(
const lldb::ModuleSP &module_sp, DataBufferSP &data_sp,
lldb::offset_t data_offset, const FileSpec *file,
lldb::offset_t file_offset, lldb::offset_t length) {
- // We get data when we aren't trying to look for cached container information,
- // so only try and look for an architecture slice if we get data
+ // We get data when we aren't trying to look for cached container
+ // information, so only try and look for an architecture slice if we get data
if (data_sp) {
DataExtractor data;
data.SetData(data_sp, data_offset, length);
@@ -81,8 +81,8 @@ ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() {}
bool ObjectContainerUniversalMachO::ParseHeader() {
bool success = ParseHeader(m_data, m_header, m_fat_archs);
- // We no longer need any data, we parsed all we needed to parse
- // and cached it in m_header and m_fat_archs
+ // We no longer need any data, we parsed all we needed to parse and cached it
+ // in m_header and m_fat_archs
m_data.Clear();
return success;
}
@@ -92,8 +92,7 @@ bool ObjectContainerUniversalMachO::ParseHeader(
std::vector<llvm::MachO::fat_arch> &fat_archs) {
bool success = false;
// Store the file offset for this universal file as we could have a universal
- // .o file
- // in a BSD archive, or be contained in another kind of object.
+ // .o file in a BSD archive, or be contained in another kind of object.
// Universal mach-o files always have their headers in big endian.
lldb::offset_t offset = 0;
data.SetByteOrder(eByteOrderBig);
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index 39ea49208700..16cbb6e5753b 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -140,13 +140,12 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data,
if (data.GetU32(offset, &e_flags, 1) == NULL)
return false;
- // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
- // e_shstrndx.
+ // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and e_shstrndx.
if (data.GetU16(offset, &e_ehsize, 6) == NULL)
return false;
- // Initialize e_phnum, e_shnum, and e_shstrndx with the values
- // read from the header.
+ // Initialize e_phnum, e_shnum, and e_shstrndx with the values read from the
+ // header.
e_phnum = e_phnum_hdr;
e_shnum = e_shnum_hdr;
e_shstrndx = e_shstrndx_hdr;
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.h b/source/Plugins/ObjectFile/ELF/ELFHeader.h
index 4e2d3155ebb9..faaf8be99d68 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.h
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -8,14 +8,14 @@
//===----------------------------------------------------------------------===//
//
/// @file
-/// @brief Generic structures and typedefs for ELF files.
+/// Generic structures and typedefs for ELF files.
///
/// This file provides definitions for the various entities comprising an ELF
/// file. The structures are generic in the sense that they do not correspond
/// to the exact binary layout of an ELF, but can be used to hold the
/// information present in both 32 and 64 bit variants of the format. Each
-/// entity provides a \c Parse method which is capable of transparently reading
-/// both 32 and 64 bit instances of the object.
+/// entity provides a \c Parse method which is capable of transparently
+/// reading both 32 and 64 bit instances of the object.
//===----------------------------------------------------------------------===//
#ifndef liblldb_ELFHeader_h_
@@ -35,8 +35,9 @@ namespace elf {
//------------------------------------------------------------------------------
/// @name ELF type definitions.
///
-/// Types used to represent the various components of ELF structures. All types
-/// are signed or unsigned integral types wide enough to hold values from both
+/// Types used to represent the various components of ELF structures. All
+/// types are signed or unsigned integral types wide enough to hold values
+/// from both
/// 32 and 64 bit ELF variants.
//@{
typedef uint64_t elf_addr;
@@ -51,10 +52,10 @@ typedef int64_t elf_sxword;
//------------------------------------------------------------------------------
/// @class ELFHeader
-/// @brief Generic representation of an ELF file header.
+/// Generic representation of an ELF file header.
///
-/// This object is used to identify the general attributes on an ELF file and to
-/// locate additional sections within the file.
+/// This object is used to identify the general attributes on an ELF file and
+/// to locate additional sections within the file.
struct ELFHeader {
unsigned char e_ident[llvm::ELF::EI_NIDENT]; ///< ELF file identification.
elf_addr e_entry; ///< Virtual address program entry point.
@@ -118,9 +119,9 @@ struct ELFHeader {
bool HasHeaderExtension() const;
//--------------------------------------------------------------------------
- /// Parse an ELFHeader entry starting at position \p offset and
- /// update the data extractor with the address size and byte order
- /// attributes as defined by the header.
+ /// Parse an ELFHeader entry starting at position \p offset and update the
+ /// data extractor with the address size and byte order attributes as
+ /// defined by the header.
///
/// @param[in,out] data
/// The DataExtractor to read from. Updated with the address size and
@@ -157,8 +158,8 @@ struct ELFHeader {
private:
//--------------------------------------------------------------------------
- /// Parse an ELFHeader header extension entry. This method is called
- /// by Parse().
+ /// Parse an ELFHeader header extension entry. This method is called by
+ /// Parse().
///
/// @param[in] data
/// The DataExtractor to read from.
@@ -167,7 +168,7 @@ private:
//------------------------------------------------------------------------------
/// @class ELFSectionHeader
-/// @brief Generic representation of an ELF section header.
+/// Generic representation of an ELF section header.
struct ELFSectionHeader {
elf_word sh_name; ///< Section name string index.
elf_word sh_type; ///< Section type.
@@ -202,7 +203,7 @@ struct ELFSectionHeader {
//------------------------------------------------------------------------------
/// @class ELFProgramHeader
-/// @brief Generic representation of an ELF program header.
+/// Generic representation of an ELF program header.
struct ELFProgramHeader {
elf_word p_type; ///< Type of program segment.
elf_word p_flags; ///< Segment attributes.
@@ -235,7 +236,7 @@ struct ELFProgramHeader {
//------------------------------------------------------------------------------
/// @class ELFSymbol
-/// @brief Represents a symbol within an ELF symbol table.
+/// Represents a symbol within an ELF symbol table.
struct ELFSymbol {
elf_addr st_value; ///< Absolute or relocatable address.
elf_xword st_size; ///< Size of the symbol or zero.
@@ -288,7 +289,7 @@ struct ELFSymbol {
//------------------------------------------------------------------------------
/// @class ELFDynamic
-/// @brief Represents an entry in an ELF dynamic table.
+/// Represents an entry in an ELF dynamic table.
struct ELFDynamic {
elf_sxword d_tag; ///< Type of dynamic table entry.
union {
@@ -318,7 +319,7 @@ struct ELFDynamic {
//------------------------------------------------------------------------------
/// @class ELFRel
-/// @brief Represents a relocation entry with an implicit addend.
+/// Represents a relocation entry with an implicit addend.
struct ELFRel {
elf_addr r_offset; ///< Address of reference.
elf_xword r_info; ///< symbol index and type of relocation.
@@ -360,7 +361,7 @@ struct ELFRel {
//------------------------------------------------------------------------------
/// @class ELFRela
-/// @brief Represents a relocation entry with an explicit addend.
+/// Represents a relocation entry with an explicit addend.
struct ELFRela {
elf_addr r_offset; ///< Address of reference.
elf_xword r_info; ///< Symbol index and type of relocation.
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 36027dde0432..8701908378f1 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -113,7 +113,7 @@ const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
-/// @brief Generic wrapper for ELFRel and ELFRela.
+/// Generic wrapper for ELFRel and ELFRela.
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
/// entries in a generic manner.
@@ -240,11 +240,10 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
if (data.GetU32(offset, &n_namesz, 3) == NULL)
return false;
- // The name field is required to be nul-terminated, and n_namesz
- // includes the terminating nul in observed implementations (contrary
- // to the ELF-64 spec). A special case is needed for cores generated
- // by some older Linux versions, which write a note named "CORE"
- // without a nul terminator and n_namesz = 4.
+ // The name field is required to be nul-terminated, and n_namesz includes the
+ // terminating nul in observed implementations (contrary to the ELF-64 spec).
+ // A special case is needed for cores generated by some older Linux versions,
+ // which write a note named "CORE" without a nul terminator and n_namesz = 4.
if (n_namesz == 4) {
char buf[4];
if (data.ExtractBytes(*offset, 4, data.GetByteOrder(), buf) != 4)
@@ -295,7 +294,8 @@ static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
uint32_t fileclass = header.e_ident[EI_CLASS];
- // If there aren't any elf flags available (e.g core elf file) then return default
+ // If there aren't any elf flags available (e.g core elf file) then return
+ // default
// 32 or 64 bit arch (without any architecture revision) based on object file's class.
if (header.e_type == ET_CORE) {
switch (fileclass) {
@@ -549,8 +549,8 @@ uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
DataExtractor segment_data;
if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
- // The ELF program header contained incorrect data,
- // probably corefile is incomplete or corrupted.
+ // The ELF program header contained incorrect data, probably corefile
+ // is incomplete or corrupted.
break;
}
@@ -595,8 +595,8 @@ static const char *OSABIAsCString(unsigned char osabi_byte) {
//
// WARNING : This function is being deprecated
-// It's functionality has moved to ArchSpec::SetArchitecture
-// This function is only being kept to validate the move.
+// It's functionality has moved to ArchSpec::SetArchitecture This function is
+// only being kept to validate the move.
//
// TODO : Remove this function
static bool GetOsFromOSABI(unsigned char osabi_byte,
@@ -674,29 +674,16 @@ size_t ObjectFileELF::GetModuleSpecifications(
__FUNCTION__, file.GetPath().c_str());
}
- // In case there is header extension in the section #0, the header
- // we parsed above could have sentinel values for e_phnum, e_shnum,
- // and e_shstrndx. In this case we need to reparse the header
- // with a bigger data source to get the actual values.
- size_t section_header_end = header.e_shoff + header.e_shentsize;
- if (header.HasHeaderExtension() &&
- section_header_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, section_header_end, file_offset);
- if (data_sp) {
- data.SetData(data_sp);
- lldb::offset_t header_offset = data_offset;
- header.Parse(data, &header_offset);
- }
- }
-
- // Try to get the UUID from the section list. Usually that's at the
- // end, so map the file in if we don't have it already.
- section_header_end =
- header.e_shoff + header.e_shnum * header.e_shentsize;
- if (section_header_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, section_header_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
+ data_sp = MapFileData(file, -1, file_offset);
+ if (data_sp)
+ data.SetData(data_sp);
+ // In case there is header extension in the section #0, the header we
+ // parsed above could have sentinel values for e_phnum, e_shnum, and
+ // e_shstrndx. In this case we need to reparse the header with a
+ // bigger data source to get the actual values.
+ if (header.HasHeaderExtension()) {
+ lldb::offset_t header_offset = data_offset;
+ header.Parse(data, &header_offset);
}
uint32_t gnu_debuglink_crc = 0;
@@ -733,51 +720,27 @@ size_t ObjectFileELF::GetModuleSpecifications(
// contents crc32 would be too much of luxury. Thus we will need
// to fallback to something simpler.
if (header.e_type == llvm::ELF::ET_CORE) {
- size_t program_headers_end =
- header.e_phoff + header.e_phnum * header.e_phentsize;
- if (program_headers_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, program_headers_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
- }
ProgramHeaderColl program_headers;
GetProgramHeaderInfo(program_headers, data, header);
- size_t segment_data_end = 0;
- for (ProgramHeaderCollConstIter I = program_headers.begin();
- I != program_headers.end(); ++I) {
- segment_data_end = std::max<unsigned long long>(
- I->p_offset + I->p_filesz, segment_data_end);
- }
-
- if (segment_data_end > data_sp->GetByteSize()) {
- data_sp = MapFileData(file, segment_data_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
- }
-
core_notes_crc =
CalculateELFNotesSegmentsCRC32(program_headers, data);
} else {
- // Need to map entire file into memory to calculate the crc.
- data_sp = MapFileData(file, -1, file_offset);
- if (data_sp) {
- data.SetData(data_sp);
- gnu_debuglink_crc = calc_gnu_debuglink_crc32(
- data.GetDataStart(), data.GetByteSize());
- }
+ gnu_debuglink_crc = calc_gnu_debuglink_crc32(
+ data.GetDataStart(), data.GetByteSize());
}
}
+ using u32le = llvm::support::ulittle32_t;
if (gnu_debuglink_crc) {
// Use 4 bytes of crc from the .gnu_debuglink section.
- uint32_t uuidt[4] = {gnu_debuglink_crc, 0, 0, 0};
- uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data(gnu_debuglink_crc);
+ uuid = UUID::fromData(&data, sizeof(data));
} else if (core_notes_crc) {
// Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make
- // it look different form
- // .gnu_debuglink crc followed by 4 bytes of note segments crc.
- uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
- uuid.SetBytes(uuidt, sizeof(uuidt));
+ // it look different form .gnu_debuglink crc followed by 4 bytes
+ // of note segments crc.
+ u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
+ uuid = UUID::fromData(data, sizeof(data));
}
}
@@ -861,21 +824,19 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
size_t sect_idx = 0;
for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find all
- // of the sections that have SHF_ALLOC in their flag bits.
+ // Iterate through the object file sections to find all of the sections
+ // that have SHF_ALLOC in their flag bits.
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && section_sp->Test(SHF_ALLOC)) {
lldb::addr_t load_addr = section_sp->GetFileAddress();
// We don't want to update the load address of a section with type
// eSectionTypeAbsoluteAddress as they already have the absolute load
- // address
- // already specified
+ // address already specified
if (section_sp->GetType() != eSectionTypeAbsoluteAddress)
load_addr += value;
// On 32-bit systems the load address have to fit into 4 bytes. The
- // rest of
- // the bytes are the overflow from the addition.
+ // rest of the bytes are the overflow from the addition.
if (GetAddressByteSize() == 4)
load_addr &= 0xFFFFFFFF;
@@ -905,24 +866,23 @@ uint32_t ObjectFileELF::GetAddressByteSize() const {
AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
Symtab *symtab = GetSymtab();
if (!symtab)
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
- // The address class is determined based on the symtab. Ask it from the object
- // file what
- // contains the symtab information.
+ // The address class is determined based on the symtab. Ask it from the
+ // object file what contains the symtab information.
ObjectFile *symtab_objfile = symtab->GetObjectFile();
if (symtab_objfile != nullptr && symtab_objfile != this)
return symtab_objfile->GetAddressClass(file_addr);
auto res = ObjectFile::GetAddressClass(file_addr);
- if (res != eAddressClassCode)
+ if (res != AddressClass::eCode)
return res;
auto ub = m_address_class_map.upper_bound(file_addr);
if (ub == m_address_class_map.begin()) {
- // No entry in the address class map before the address. Return
- // default address class for an address in a code section.
- return eAddressClassCode;
+ // No entry in the address class map before the address. Return default
+ // address class for an address in a code section.
+ return AddressClass::eCode;
}
// Move iterator to the address class entry preceding address
@@ -950,6 +910,7 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
return false;
+ using u32le = llvm::support::ulittle32_t;
if (m_uuid.IsValid()) {
// We have the full build id uuid.
*uuid = m_uuid;
@@ -963,11 +924,11 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
core_notes_crc = CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
if (core_notes_crc) {
- // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
- // look different form .gnu_debuglink crc - followed by 4 bytes of note
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it look
+ // different form .gnu_debuglink crc - followed by 4 bytes of note
// segments crc.
- uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
- m_uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
+ m_uuid = UUID::fromData(data, sizeof(data));
}
} else {
if (!m_gnu_debuglink_crc)
@@ -975,8 +936,8 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
calc_gnu_debuglink_crc32(m_data.GetDataStart(), m_data.GetByteSize());
if (m_gnu_debuglink_crc) {
// Use 4 bytes of crc from the .gnu_debuglink section.
- uint32_t uuidt[4] = {m_gnu_debuglink_crc, 0, 0, 0};
- m_uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data(m_gnu_debuglink_crc);
+ m_uuid = UUID::fromData(&data, sizeof(data));
}
}
@@ -1034,8 +995,8 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) {
ELFDynamic &symbol = m_dynamic_symbols[i];
if (symbol.d_tag == DT_DEBUG) {
- // Compute the offset as the number of previous entries plus the
- // size of d_tag.
+ // Compute the offset as the number of previous entries plus the size of
+ // d_tag.
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
return Address(dynsym_section_sp, offset);
}
@@ -1314,18 +1275,16 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// Only bother processing this if we don't already have the uuid set.
if (!uuid.IsValid()) {
// 16 bytes is UUID|MD5, 20 bytes is SHA1. Other linkers may produce a
- // build-id of a different
- // length. Accept it as long as it's at least 4 bytes as it will be
- // better than our own crc32.
- if (note.n_descsz >= 4 && note.n_descsz <= 20) {
- uint8_t uuidbuf[20];
- if (data.GetU8(&offset, &uuidbuf, note.n_descsz) == nullptr) {
+ // build-id of a different length. Accept it as long as it's at least
+ // 4 bytes as it will be better than our own crc32.
+ if (note.n_descsz >= 4) {
+ if (const uint8_t *buf = data.PeekData(offset, note.n_descsz)) {
+ // Save the build id as the UUID for the module.
+ uuid = UUID::fromData(buf, note.n_descsz);
+ } else {
error.SetErrorString("failed to read GNU_BUILD_ID note payload");
return error;
}
-
- // Save the build id as the UUID for the module.
- uuid.SetBytes(uuidbuf, note.n_descsz);
}
}
break;
@@ -1368,8 +1327,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
// TODO At some point the description string could be processed.
- // It could provide a steer towards the kalimba variant which
- // this ELF targets.
+ // It could provide a steer towards the kalimba variant which this ELF
+ // targets.
if (note.n_descsz) {
const char *cstr =
data.GetCStr(&offset, llvm::alignTo(note.n_descsz, 4));
@@ -1384,36 +1343,28 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// register info
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
} else if (note.n_name == LLDB_NT_OWNER_CORE) {
- // Parse the NT_FILE to look for stuff in paths to shared libraries
- // As the contents look like this in a 64 bit ELF core file:
- // count = 0x000000000000000a (10)
- // page_size = 0x0000000000001000 (4096)
- // Index start end file_ofs path
- // ===== ------------------ ------------------ ------------------
- // -------------------------------------
- // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000
- // /tmp/a.out
- // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000
- // /tmp/a.out
- // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001
- // /tmp/a.out
+ // Parse the NT_FILE to look for stuff in paths to shared libraries As
+ // the contents look like this in a 64 bit ELF core file: count =
+ // 0x000000000000000a (10) page_size = 0x0000000000001000 (4096) Index
+ // start end file_ofs path =====
+ // ------------------ ------------------ ------------------
+ // ------------------------------------- [ 0] 0x0000000000400000
+ // 0x0000000000401000 0x0000000000000000 /tmp/a.out [ 1]
+ // 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out [
+ // 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
// [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be
- // /lib/x86_64-linux-gnu/libc-2.19.so
- // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000
- // /lib/x86_64-linux-gnu/ld-2.19.so
- // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022
- // /lib/x86_64-linux-gnu/ld-2.19.so
- // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023
- // /lib/x86_64-linux-gnu/ld-2.19.so
- // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
- // uint32_t
- // For reference: see readelf source code (in binutils).
+ // /lib/x86_64-linux-gnu/libc-2.19.so [ 4] 0x00007fa79cba8000
+ // 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-
+ // gnu/libc-2.19.so [ 5] 0x00007fa79cda7000 0x00007fa79cdab000
+ // 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so [ 6]
+ // 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64
+ // -linux-gnu/libc-2.19.so [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000
+ // 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so [ 8]
+ // 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64
+ // -linux-gnu/ld-2.19.so [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000
+ // 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so In the 32 bit ELFs
+ // the count, page_size, start, end, file_ofs are uint32_t For reference:
+ // see readelf source code (in binutils).
if (note.n_type == NT_FILE) {
uint64_t count = data.GetAddress(&offset);
const char *cstr;
@@ -1437,15 +1388,14 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
}
if (arch_spec.IsMIPS() &&
arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS)
- // In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing
- // for some cases (e.g. compile with -nostdlib)
- // Hence set OS to Linux
+ // In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing for some
+ // cases (e.g. compile with -nostdlib) Hence set OS to Linux
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
}
}
- // Calculate the offset of the next note just in case "offset" has been used
- // to poke at the contents of the note data
+ // Calculate the offset of the next note just in case "offset" has been
+ // used to poke at the contents of the note data
offset = note_offset + note.GetByteSize();
}
@@ -1545,13 +1495,12 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
arch_spec.SetArchitecture(eArchTypeELF, header.e_machine, sub_type,
header.e_ident[EI_OSABI]);
- // Validate if it is ok to remove GetOsFromOSABI.
- // Note, that now the OS is determined based on EI_OSABI flag and
- // the info extracted from ELF notes (see RefineModuleDetailsFromNote).
- // However in some cases that still might be not enough: for example
- // a shared library might not have any notes at all
- // and have EI_OSABI flag set to System V,
- // as result the OS will be set to UnknownOS.
+ // Validate if it is ok to remove GetOsFromOSABI. Note, that now the OS is
+ // determined based on EI_OSABI flag and the info extracted from ELF notes
+ // (see RefineModuleDetailsFromNote). However in some cases that still
+ // might be not enough: for example a shared library might not have any
+ // notes at all and have EI_OSABI flag set to System V, as result the OS
+ // will be set to UnknownOS.
GetOsFromOSABI(header.e_ident[EI_OSABI], ostype);
spec_ostype = arch_spec.GetTriple().getOS();
assert(spec_ostype == ostype);
@@ -1842,6 +1791,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
static ConstString g_sect_name_dwarf_debug_macro(".debug_macro");
+ static ConstString g_sect_name_dwarf_debug_names(".debug_names");
static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
@@ -1857,10 +1807,12 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
static ConstString g_sect_name_dwarf_debug_str_dwo(".debug_str.dwo");
static ConstString g_sect_name_dwarf_debug_str_offsets_dwo(
".debug_str_offsets.dwo");
+ static ConstString g_sect_name_dwarf_debug_types(".debug_types");
static ConstString g_sect_name_eh_frame(".eh_frame");
static ConstString g_sect_name_arm_exidx(".ARM.exidx");
static ConstString g_sect_name_arm_extab(".ARM.extab");
static ConstString g_sect_name_go_symtab(".gosymtab");
+ static ConstString g_sect_name_dwarf_gnu_debugaltlink(".gnu_debugaltlink");
SectionType sect_type = eSectionTypeOther;
@@ -1881,23 +1833,19 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
}
// .debug_abbrev – Abbreviations used in the .debug_info section
// .debug_aranges – Lookup table for mapping addresses to compilation
- // units
- // .debug_frame – Call frame information
- // .debug_info – The core DWARF information section
- // .debug_line – Line number information
+ // units .debug_frame – Call frame information .debug_info – The core
+ // DWARF information section .debug_line – Line number information
// .debug_loc – Location lists used in DW_AT_location attributes
- // .debug_macinfo – Macro information
- // .debug_pubnames – Lookup table for mapping object and function names to
- // compilation units
+ // .debug_macinfo – Macro information .debug_pubnames – Lookup table
+ // for mapping object and function names to compilation units
// .debug_pubtypes – Lookup table for mapping type names to compilation
- // units
- // .debug_ranges – Address ranges used in DW_AT_ranges attributes
- // .debug_str – String table used in .debug_info
- // MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section,
- // http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
- // MISSING? .debug-index -
- // http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
- // MISSING? .debug_types - Type descriptions from DWARF 4? See
+ // units .debug_ranges – Address ranges used in DW_AT_ranges attributes
+ // .debug_str – String table used in .debug_info MISSING?
+ // .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section,
+ // http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html MISSING?
+ // .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build
+ // /gdb-add-index?pathrev=144644 MISSING? .debug_types - Type
+ // descriptions from DWARF 4? See
// http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
else if (name == g_sect_name_dwarf_debug_abbrev)
sect_type = eSectionTypeDWARFDebugAbbrev;
@@ -1919,6 +1867,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
sect_type = eSectionTypeDWARFDebugMacInfo;
else if (name == g_sect_name_dwarf_debug_macro)
sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_names)
+ sect_type = eSectionTypeDWARFDebugNames;
else if (name == g_sect_name_dwarf_debug_pubnames)
sect_type = eSectionTypeDWARFDebugPubNames;
else if (name == g_sect_name_dwarf_debug_pubtypes)
@@ -1927,6 +1877,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
sect_type = eSectionTypeDWARFDebugRanges;
else if (name == g_sect_name_dwarf_debug_str)
sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_types)
+ sect_type = eSectionTypeDWARFDebugTypes;
else if (name == g_sect_name_dwarf_debug_str_offsets)
sect_type = eSectionTypeDWARFDebugStrOffsets;
else if (name == g_sect_name_dwarf_debug_abbrev_dwo)
@@ -1951,6 +1903,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
sect_type = eSectionTypeARMextab;
else if (name == g_sect_name_go_symtab)
sect_type = eSectionTypeGoSymtab;
+ else if (name == g_sect_name_dwarf_gnu_debugaltlink)
+ sect_type = eSectionTypeDWARFGNUDebugAltLink;
const uint32_t permissions =
((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0u) |
@@ -1978,13 +1932,21 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
if (eSectionTypeOther == sect_type) {
// the kalimba toolchain assumes that ELF section names are free-form.
- // It does
- // support linkscripts which (can) give rise to various arbitrarily
- // named
- // sections being "Code" or "Data".
+ // It does support linkscripts which (can) give rise to various
+ // arbitrarily named sections being "Code" or "Data".
sect_type = kalimbaSectionType(m_header, header);
}
+ // In common case ELF code section can have arbitrary name (for example,
+ // we can specify it using section attribute for particular function) so
+ // assume that section is a code section if it has SHF_EXECINSTR flag set
+ // and has SHT_PROGBITS type.
+ if (eSectionTypeOther == sect_type &&
+ llvm::ELF::SHT_PROGBITS == header.sh_type &&
+ (header.sh_flags & SHF_EXECINSTR)) {
+ sect_type = eSectionTypeCode;
+ }
+
const uint32_t target_bytes_size =
(eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type)
? m_arch_spec.GetDataByteSize()
@@ -2024,46 +1986,16 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
}
}
- if (m_sections_ap.get()) {
- if (GetType() == eTypeDebugInfo) {
- static const SectionType g_sections[] = {
- eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
- eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
- eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,
- eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc,
- eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames,
- eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
- eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets,
- eSectionTypeELFSymbolTable,
- };
- SectionList *elf_section_list = m_sections_ap.get();
- for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]);
- ++idx) {
- SectionType section_type = g_sections[idx];
- SectionSP section_sp(
- elf_section_list->FindSectionByType(section_type, true));
- if (section_sp) {
- SectionSP module_section_sp(
- unified_section_list.FindSectionByType(section_type, true));
- if (module_section_sp)
- unified_section_list.ReplaceSection(module_section_sp->GetID(),
- section_sp);
- else
- unified_section_list.AddSection(section_sp);
- }
- }
- } else {
- unified_section_list = *m_sections_ap;
- }
- }
+ // For eTypeDebugInfo files, the Symbol Vendor will take care of updating the
+ // unified section list.
+ if (GetType() != eTypeDebugInfo)
+ unified_section_list = *m_sections_ap;
}
// Find the arm/aarch64 mapping symbol character in the given symbol name.
-// Mapping symbols have the
-// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping
-// symbol prefixed by
-// an arbitrary string because if a symbol prefix added to each symbol in the
-// object file with
+// Mapping symbols have the form of "$<char>[.<any>]*". Additionally we
+// recognize cases when the mapping symbol prefixed by an arbitrary string
+// because if a symbol prefix added to each symbol in the object file with
// objcopy then the mapping symbols are also prefixed.
static char FindArmAarch64MappingSymbol(const char *symbol_name) {
if (!symbol_name)
@@ -2105,22 +2037,18 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
static ConstString opd_section_name(".opd"); // For ppc64
// On Android the oatdata and the oatexec symbols in the oat and odex files
- // covers the full
- // .text section what causes issues with displaying unusable symbol name to
- // the user and very
- // slow unwinding speed because the instruction emulation based unwind plans
- // try to emulate all
- // instructions in these symbols. Don't add these symbols to the symbol list
- // as they have no
- // use for the debugger and they are causing a lot of trouble.
- // Filtering can't be restricted to Android because this special object file
- // don't contain the
- // note section specifying the environment to Android but the custom extension
- // and file name
- // makes it highly unlikely that this will collide with anything else.
+ // covers the full .text section what causes issues with displaying unusable
+ // symbol name to the user and very slow unwinding speed because the
+ // instruction emulation based unwind plans try to emulate all instructions
+ // in these symbols. Don't add these symbols to the symbol list as they have
+ // no use for the debugger and they are causing a lot of trouble. Filtering
+ // can't be restricted to Android because this special object file don't
+ // contain the note section specifying the environment to Android but the
+ // custom extension and file name makes it highly unlikely that this will
+ // collide with anything else.
ConstString file_extension = m_file.GetFileNameExtension();
- bool skip_oatdata_oatexec = file_extension == ConstString("oat") ||
- file_extension == ConstString("odex");
+ bool skip_oatdata_oatexec = file_extension == ConstString(".oat") ||
+ file_extension == ConstString(".odex");
ArchSpec arch;
GetArchitecture(arch);
@@ -2129,8 +2057,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
module_sp ? module_sp->GetSectionList() : nullptr;
// Local cache to avoid doing a FindSectionByName for each symbol. The "const
- // char*" key must
- // came from a ConstString object so they can be compared by pointer
+ // char*" key must came from a ConstString object so they can be compared by
+ // pointer
std::unordered_map<const char *, lldb::SectionSP> section_name_to_section;
unsigned i;
@@ -2148,8 +2076,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
continue;
// Skipping oatdata and oatexec sections if it is requested. See details
- // above the
- // definition of skip_oatdata_oatexec for the reasons.
+ // above the definition of skip_oatdata_oatexec for the reasons.
if (skip_oatdata_oatexec && (::strcmp(symbol_name, "oatdata") == 0 ||
::strcmp(symbol_name, "oatexec") == 0))
continue;
@@ -2180,8 +2107,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
break;
case STT_OBJECT:
- // The symbol is associated with a data object, such as a variable,
- // an array, etc.
+ // The symbol is associated with a data object, such as a variable, an
+ // array, etc.
symbol_type = eSymbolTypeData;
break;
@@ -2192,13 +2119,13 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
case STT_SECTION:
// The symbol is associated with a section. Symbol table entries of
- // this type exist primarily for relocation and normally have
- // STB_LOCAL binding.
+ // this type exist primarily for relocation and normally have STB_LOCAL
+ // binding.
break;
case STT_FILE:
- // Conventionally, the symbol's name gives the name of the source
- // file associated with the object file. A file symbol has STB_LOCAL
+ // Conventionally, the symbol's name gives the name of the source file
+ // associated with the object file. A file symbol has STB_LOCAL
// binding, its section index is SHN_ABS, and it precedes the other
// STB_LOCAL symbols for the file, if it is present.
symbol_type = eSymbolTypeSourceFile;
@@ -2240,18 +2167,18 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'a':
// $a[.<any>]* - marks an ARM instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
break;
case 'b':
case 't':
// $b[.<any>]* - marks a THUMB BL instruction sequence
// $t[.<any>]* - marks a THUMB instruction sequence
m_address_class_map[symbol.st_value] =
- eAddressClassCodeAlternateISA;
+ AddressClass::eCodeAlternateISA;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2265,11 +2192,11 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'x':
// $x[.<any>]* - marks an A64 instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2281,18 +2208,17 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (arch.GetMachine() == llvm::Triple::arm) {
if (symbol_type == eSymbolTypeCode) {
if (symbol.st_value & 1) {
- // Subtracting 1 from the address effectively unsets
- // the low order bit, which results in the address
- // actually pointing to the beginning of the symbol.
- // This delta will be used below in conjunction with
- // symbol.st_value to produce the final symbol_value
- // that we store in the symtab.
+ // Subtracting 1 from the address effectively unsets the low order
+ // bit, which results in the address actually pointing to the
+ // beginning of the symbol. This delta will be used below in
+ // conjunction with symbol.st_value to produce the final
+ // symbol_value that we store in the symtab.
symbol_value_offset = -1;
m_address_class_map[symbol.st_value ^ 1] =
- eAddressClassCodeAlternateISA;
+ AddressClass::eCodeAlternateISA;
} else {
// This address is ARM
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
}
}
}
@@ -2317,36 +2243,32 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
llvm_arch == llvm::Triple::mips64 ||
llvm_arch == llvm::Triple::mips64el) {
if (IS_MICROMIPS(symbol.st_other))
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
symbol.st_value = symbol.st_value & (~1ull);
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
} else {
if (symbol_type == eSymbolTypeCode)
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
else if (symbol_type == eSymbolTypeData)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
else
- m_address_class_map[symbol.st_value] = eAddressClassUnknown;
+ m_address_class_map[symbol.st_value] = AddressClass::eUnknown;
}
}
}
// symbol_value_offset may contain 0 for ARM symbols or -1 for THUMB
- // symbols. See above for
- // more details.
+ // symbols. See above for more details.
uint64_t symbol_value = symbol.st_value + symbol_value_offset;
if (symbol_section_sp == nullptr && section_idx == SHN_ABS &&
symbol.st_size != 0) {
// We don't have a section for a symbol with non-zero size. Create a new
- // section for it
- // so the address range covered by the symbol is also covered by the
- // module (represented
- // through the section list). It is needed so module lookup for the
- // addresses covered
- // by this symbol will be successfull. This case happens for absolute
- // symbols.
+ // section for it so the address range covered by the symbol is also
+ // covered by the module (represented through the section list). It is
+ // needed so module lookup for the addresses covered by this symbol will
+ // be successfull. This case happens for absolute symbols.
ConstString fake_section_name(std::string(".absolute.") + symbol_name);
symbol_section_sp =
std::make_shared<Section>(module_sp, this, SHN_ABS, fake_section_name,
@@ -2389,8 +2311,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
Mangled mangled(ConstString(symbol_bare), is_mangled);
// Now append the suffix back to mangled and unmangled names. Only do it if
- // the
- // demangling was successful (string is not empty).
+ // the demangling was successful (string is not empty).
if (has_suffix) {
llvm::StringRef suffix = symbol_ref.substr(version_pos);
@@ -2406,12 +2327,10 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
}
// In ELF all symbol should have a valid size but it is not true for some
- // function symbols
- // coming from hand written assembly. As none of the function symbol should
- // have 0 size we
- // try to calculate the size for these symbols in the symtab with saying
- // that their original
- // size is not valid.
+ // function symbols coming from hand written assembly. As none of the
+ // function symbol should have 0 size we try to calculate the size for
+ // these symbols in the symtab with saying that their original size is not
+ // valid.
bool symbol_size_valid =
symbol.st_size != 0 || symbol.getType() != STT_FUNC;
@@ -2440,8 +2359,7 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
lldb_private::Section *symtab) {
if (symtab->GetObjectFile() != this) {
// If the symbol table section is owned by a different object file, have it
- // do the
- // parsing.
+ // do the parsing.
ObjectFileELF *obj_file_elf =
static_cast<ObjectFileELF *>(symtab->GetObjectFile());
return obj_file_elf->ParseSymbolTable(symbol_table, start_id, symtab);
@@ -2457,8 +2375,8 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
- // sh_link: section header index of associated string table.
- // Section ID's are ones based.
+ // sh_link: section header index of associated string table. Section ID's are
+ // ones based.
user_id_t strtab_id = symtab_hdr->sh_link + 1;
Section *strtab = section_list->FindSectionByID(strtab_id).get();
@@ -2543,19 +2461,17 @@ unsigned ObjectFileELF::PLTRelocationType() {
return 0;
}
-// Returns the size of the normal plt entries and the offset of the first normal
-// plt entry. The
-// 0th entry in the plt table is usually a resolution entry which have different
-// size in some
-// architectures then the rest of the plt entries.
+// Returns the size of the normal plt entries and the offset of the first
+// normal plt entry. The 0th entry in the plt table is usually a resolution
+// entry which have different size in some architectures then the rest of the
+// plt entries.
static std::pair<uint64_t, uint64_t>
GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
const ELFSectionHeader *plt_hdr) {
const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
- // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16
- // bytes.
- // So round the entsize up by the alignment if addralign is set.
+ // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are
+ // 16 bytes. So round the entsize up by the alignment if addralign is set.
elf_xword plt_entsize =
plt_hdr->sh_addralign
? llvm::alignTo(plt_hdr->sh_entsize, plt_hdr->sh_addralign)
@@ -2567,12 +2483,10 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
// just in case.
if (plt_entsize <= 4) {
// The linker haven't set the plt_hdr->sh_entsize field. Try to guess the
- // size of the plt
- // entries based on the number of entries and the size of the plt section
- // with the
- // assumption that the size of the 0th entry is at least as big as the size
- // of the normal
- // entries and it isn't much bigger then that.
+ // size of the plt entries based on the number of entries and the size of
+ // the plt section with the assumption that the size of the 0th entry is at
+ // least as big as the size of the normal entries and it isn't much bigger
+ // then that.
if (plt_hdr->sh_addralign)
plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign /
(num_relocations + 1) * plt_hdr->sh_addralign;
@@ -2865,8 +2779,7 @@ Symtab *ObjectFileELF::GetSymtab() {
return NULL;
// We always want to use the main object file so we (hopefully) only have one
- // cached copy
- // of our symtab, dynamic sections, etc.
+ // cached copy of our symtab, dynamic sections, etc.
ObjectFile *module_obj_file = module_sp->GetObjectFile();
if (module_obj_file && module_obj_file != this)
return module_obj_file->GetSymtab();
@@ -2881,18 +2794,15 @@ Symtab *ObjectFileELF::GetSymtab() {
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a
- // smaller
- // version of the symtab that only contains global symbols. The information
- // found
- // in the dynsym is therefore also found in the symtab, while the reverse is
- // not
- // necessarily true.
+ // smaller version of the symtab that only contains global symbols. The
+ // information found in the dynsym is therefore also found in the symtab,
+ // while the reverse is not necessarily true.
Section *symtab =
section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
if (!symtab) {
// The symtab section is non-allocable and can be stripped, so if it
- // doesn't exist
- // then use the dynsym section which should always be there.
+ // doesn't exist then use the dynsym section which should always be
+ // there.
symtab =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
@@ -2939,8 +2849,7 @@ Symtab *ObjectFileELF::GetSymtab() {
}
// If we still don't have any symtab then create an empty instance to avoid
- // do the section
- // lookup next time.
+ // do the section lookup next time.
if (m_symtab_ap == nullptr)
m_symtab_ap.reset(new Symtab(this));
@@ -2954,8 +2863,8 @@ void ObjectFileELF::RelocateSection(lldb_private::Section *section)
{
static const char *debug_prefix = ".debug";
- // Set relocated bit so we stop getting called, regardless of
- // whether we actually relocate.
+ // Set relocated bit so we stop getting called, regardless of whether we
+ // actually relocate.
section->SetIsRelocated(true);
// We only relocate in ELF relocatable files
@@ -2998,12 +2907,10 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
return;
// First we save the new symbols into a separate list and add them to the
- // symbol table after
- // we colleced all symbols we want to add. This is neccessary because adding a
- // new symbol
- // invalidates the internal index of the symtab what causing the next lookup
- // to be slow because
- // it have to recalculate the index first.
+ // symbol table after we colleced all symbols we want to add. This is
+ // neccessary because adding a new symbol invalidates the internal index of
+ // the symtab what causing the next lookup to be slow because it have to
+ // recalculate the index first.
std::vector<Symbol> new_symbols;
eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols](
@@ -3197,8 +3104,8 @@ void ObjectFileELF::DumpELFProgramHeader(Stream *s,
//----------------------------------------------------------------------
// DumpELFProgramHeader_p_type
//
-// Dump an token value for the ELF program header member p_type which
-// describes the type of the program header
+// Dump an token value for the ELF program header member p_type which describes
+// the type of the program header
// ----------------------------------------------------------------------
void ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type) {
const int kStrWidth = 15;
@@ -3369,8 +3276,7 @@ bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
if (CalculateType() == eTypeCoreFile &&
m_arch_spec.TripleOSIsUnspecifiedUnknown()) {
// Core files don't have section headers yet they have PT_NOTE program
- // headers
- // that might shed more light on the architecture
+ // headers that might shed more light on the architecture
if (ParseProgramHeaders()) {
for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
@@ -3431,22 +3337,22 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
case llvm::ELF::ET_EXEC:
// 2 - Executable file
// TODO: is there any way to detect that an executable is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section headers,
+ // symbols, or any other flag bits???
return eStrataUser;
case llvm::ELF::ET_DYN:
// 3 - Shared object file
// TODO: is there any way to detect that an shared library is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section headers,
+ // symbols, or any other flag bits???
return eStrataUnknown;
case ET_CORE:
// 4 - Core file
// TODO: is there any way to detect that an core file is a kernel
- // related executable by inspecting the program headers, section
- // headers, symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section headers,
+ // symbols, or any other flag bits???
return eStrataUnknown;
default:
@@ -3491,8 +3397,9 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
size_t(section_data.GetByteSize())},
GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
if (!Decompressor) {
- LLDB_LOG(log, "Unable to initialize decompressor for section {0}: {1}",
- section->GetName(), llvm::toString(Decompressor.takeError()));
+ LLDB_LOG_ERROR(log, Decompressor.takeError(),
+ "Unable to initialize decompressor for section {0}",
+ section->GetName());
return result;
}
auto buffer_sp =
@@ -3500,10 +3407,45 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
if (auto Error = Decompressor->decompress(
{reinterpret_cast<char *>(buffer_sp->GetBytes()),
size_t(buffer_sp->GetByteSize())})) {
- LLDB_LOG(log, "Decompression of section {0} failed: {1}",
- section->GetName(), llvm::toString(std::move(Error)));
+ LLDB_LOG_ERROR(log, std::move(Error), "Decompression of section {0} failed",
+ section->GetName());
return result;
}
section_data.SetData(buffer_sp);
return buffer_sp->GetByteSize();
}
+
+bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
+ size_t header_count = ParseProgramHeaders();
+ for (size_t i = 1; i <= header_count; ++i) {
+ auto header = GetProgramHeaderByIndex(i);
+ if (header->p_paddr != 0)
+ return true;
+ }
+ return false;
+}
+
+std::vector<ObjectFile::LoadableData>
+ObjectFileELF::GetLoadableData(Target &target) {
+ // Create a list of loadable data from loadable segments, using physical
+ // addresses if they aren't all null
+ std::vector<LoadableData> loadables;
+ size_t header_count = ParseProgramHeaders();
+ bool should_use_paddr = AnySegmentHasPhysicalAddress();
+ for (size_t i = 1; i <= header_count; ++i) {
+ LoadableData loadable;
+ auto header = GetProgramHeaderByIndex(i);
+ if (header->p_type != llvm::ELF::PT_LOAD)
+ continue;
+ loadable.Dest = should_use_paddr ? header->p_paddr : header->p_vaddr;
+ if (loadable.Dest == LLDB_INVALID_ADDRESS)
+ continue;
+ if (header->p_filesz == 0)
+ continue;
+ auto segment_data = GetSegmentDataByIndex(i);
+ loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
+ segment_data.GetByteSize());
+ loadables.push_back(loadable);
+ }
+ return loadables;
+}
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 2909f4e52e4a..2664595fd81d 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -54,10 +54,10 @@ struct ELFNote {
//------------------------------------------------------------------------------
/// @class ObjectFileELF
-/// @brief Generic ELF object file reader.
+/// Generic ELF object file reader.
///
-/// This class provides a generic ELF (32/64 bit) reader plugin implementing the
-/// ObjectFile protocol.
+/// This class provides a generic ELF (32/64 bit) reader plugin implementing
+/// the ObjectFile protocol.
class ObjectFileELF : public lldb_private::ObjectFile {
public:
~ObjectFileELF() override;
@@ -113,7 +113,7 @@ public:
uint32_t GetAddressByteSize() const override;
- lldb::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
+ lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
lldb_private::Symtab *GetSymtab() override;
@@ -161,6 +161,11 @@ public:
void RelocateSection(lldb_private::Section *section) override;
+protected:
+
+ std::vector<LoadableData>
+ GetLoadableData(lldb_private::Target &target) override;
+
private:
ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
lldb::offset_t data_offset, const lldb_private::FileSpec *file,
@@ -186,7 +191,7 @@ private:
typedef DynamicSymbolColl::iterator DynamicSymbolCollIter;
typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;
- typedef std::map<lldb::addr_t, lldb::AddressClass>
+ typedef std::map<lldb::addr_t, lldb_private::AddressClass>
FileAddressToAddressClassMap;
/// Version of this reader common to all plugins based on this class.
@@ -255,8 +260,8 @@ private:
uint64_t length,
lldb_private::ArchSpec &arch_spec);
- /// Parses the elf section headers and returns the uuid, debug link name, crc,
- /// archspec.
+ /// Parses the elf section headers and returns the uuid, debug link name,
+ /// crc, archspec.
static size_t GetSectionHeaderInfo(SectionHeaderColl &section_headers,
lldb_private::DataExtractor &object_data,
const elf::ELFHeader &header,
@@ -383,6 +388,8 @@ private:
RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
lldb_private::ArchSpec &arch_spec,
lldb_private::UUID &uuid);
+
+ bool AnySegmentHasPhysicalAddress();
};
#endif // liblldb_ObjectFileELF_h_
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index a9ab366fbf53..af040322ec52 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -65,8 +65,8 @@ ObjectFile *ObjectFileJIT::CreateInstance(const lldb::ModuleSP &module_sp,
const FileSpec *file,
lldb::offset_t file_offset,
lldb::offset_t length) {
- // JIT'ed object file is backed by the ObjectFileJITDelegate, never
- // read from a file
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
+ // a file
return NULL;
}
@@ -74,8 +74,8 @@ ObjectFile *ObjectFileJIT::CreateMemoryInstance(const lldb::ModuleSP &module_sp,
DataBufferSP &data_sp,
const ProcessSP &process_sp,
lldb::addr_t header_addr) {
- // JIT'ed object file is backed by the ObjectFileJITDelegate, never
- // read from memory
+ // JIT'ed object file is backed by the ObjectFileJITDelegate, never read from
+ // memory
return NULL;
}
@@ -214,9 +214,8 @@ bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
const size_t num_sections = section_list->GetSize();
// "value" is an offset to apply to each top level segment
for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find all
- // of the sections that size on disk (to avoid __PAGEZERO)
- // and load them
+ // Iterate through the object file sections to find all of the sections
+ // that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && section_sp->GetFileSize() > 0 &&
section_sp->IsThreadSpecific() == false) {
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index e6941c9f6ed6..91e7f3353270 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -161,8 +161,7 @@ public:
case 7:
case 8:
case 9:
- // fancy flavors that encapsulate of the above
- // flavors...
+ // fancy flavors that encapsulate of the above flavors...
break;
default:
@@ -393,8 +392,7 @@ public:
case 7:
case 8:
case 9:
- // fancy flavors that encapsulate of the above
- // flavors...
+ // fancy flavors that encapsulate of the above flavors...
break;
default:
@@ -517,8 +515,7 @@ public:
}
// Note that gpr.cpsr is also copied by the above loop; this loop
- // technically extends
- // one element past the end of the gpr.r[] array.
+ // technically extends one element past the end of the gpr.r[] array.
SetError(GPRRegSet, Read, 0);
offset = next_thread_state;
@@ -1164,19 +1161,19 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
const lldb::SectionType section_type = section_sp->GetType();
switch (section_type) {
case eSectionTypeInvalid:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSectionTypeCode:
if (m_header.cputype == llvm::MachO::CPU_TYPE_ARM) {
- // For ARM we have a bit in the n_desc field of the symbol
- // that tells us ARM/Thumb which is bit 0x0008.
+ // For ARM we have a bit in the n_desc field of the symbol that
+ // tells us ARM/Thumb which is bit 0x0008.
if (symbol->GetFlags() & MACHO_NLIST_ARM_SYMBOL_IS_THUMB)
- return eAddressClassCodeAlternateISA;
+ return AddressClass::eCodeAlternateISA;
}
- return eAddressClassCode;
+ return AddressClass::eCode;
case eSectionTypeContainer:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSectionTypeData:
case eSectionTypeDataCString:
@@ -1190,7 +1187,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
case eSectionTypeDataObjCMessageRefs:
case eSectionTypeDataObjCCFStrings:
case eSectionTypeGoSymtab:
- return eAddressClassData;
+ return AddressClass::eData;
case eSectionTypeDebug:
case eSectionTypeDWARFDebugAbbrev:
@@ -1203,22 +1200,25 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
case eSectionTypeDWARFDebugLoc:
case eSectionTypeDWARFDebugMacInfo:
case eSectionTypeDWARFDebugMacro:
+ case eSectionTypeDWARFDebugNames:
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
case eSectionTypeDWARFDebugStr:
case eSectionTypeDWARFDebugStrOffsets:
+ case eSectionTypeDWARFDebugTypes:
case eSectionTypeDWARFAppleNames:
case eSectionTypeDWARFAppleTypes:
case eSectionTypeDWARFAppleNamespaces:
case eSectionTypeDWARFAppleObjC:
- return eAddressClassDebug;
+ case eSectionTypeDWARFGNUDebugAltLink:
+ return AddressClass::eDebug;
case eSectionTypeEHFrame:
case eSectionTypeARMexidx:
case eSectionTypeARMextab:
case eSectionTypeCompactUnwind:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSectionTypeAbsoluteAddress:
case eSectionTypeELFSymbolTable:
@@ -1226,7 +1226,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
case eSectionTypeELFRelocationEntries:
case eSectionTypeELFDynamicLinkInfo:
case eSectionTypeOther:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
}
}
}
@@ -1234,73 +1234,73 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
const SymbolType symbol_type = symbol->GetType();
switch (symbol_type) {
case eSymbolTypeAny:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeAbsolute:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeCode:
case eSymbolTypeTrampoline:
case eSymbolTypeResolver:
if (m_header.cputype == llvm::MachO::CPU_TYPE_ARM) {
- // For ARM we have a bit in the n_desc field of the symbol
- // that tells us ARM/Thumb which is bit 0x0008.
+ // For ARM we have a bit in the n_desc field of the symbol that tells
+ // us ARM/Thumb which is bit 0x0008.
if (symbol->GetFlags() & MACHO_NLIST_ARM_SYMBOL_IS_THUMB)
- return eAddressClassCodeAlternateISA;
+ return AddressClass::eCodeAlternateISA;
}
- return eAddressClassCode;
+ return AddressClass::eCode;
case eSymbolTypeData:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeRuntime:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeException:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeSourceFile:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeHeaderFile:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeObjectFile:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeCommonBlock:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeBlock:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeLocal:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeParam:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeVariable:
- return eAddressClassData;
+ return AddressClass::eData;
case eSymbolTypeVariableType:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeLineEntry:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeLineHeader:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeScopeBegin:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeScopeEnd:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeAdditional:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeCompiler:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeInstrumentation:
- return eAddressClassDebug;
+ return AddressClass::eDebug;
case eSymbolTypeUndefined:
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
case eSymbolTypeObjCClass:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeObjCMetaClass:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeObjCIVar:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
case eSymbolTypeReExported:
- return eAddressClassRuntime;
+ return AddressClass::eRuntime;
}
}
}
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
}
Symtab *ObjectFileMachO::GetSymtab() {
@@ -1349,586 +1349,565 @@ bool ObjectFileMachO::IsStripped() {
return false;
}
-void ObjectFileMachO::CreateSections(SectionList &unified_section_list) {
- if (!m_sections_ap.get()) {
- m_sections_ap.reset(new SectionList());
+ObjectFileMachO::EncryptedFileRanges ObjectFileMachO::GetEncryptedFileRanges() {
+ EncryptedFileRanges result;
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
- const bool is_dsym = (m_header.filetype == MH_DSYM);
- lldb::user_id_t segID = 0;
- lldb::user_id_t sectID = 0;
- lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
- uint32_t i;
- const bool is_core = GetType() == eTypeCoreFile;
- // bool dump_sections = false;
- ModuleSP module_sp(GetModule());
- // First look up any LC_ENCRYPTION_INFO load commands
- typedef RangeArray<uint32_t, uint32_t, 8> EncryptedFileRanges;
- EncryptedFileRanges encrypted_file_ranges;
- encryption_info_command encryption_cmd;
- for (i = 0; i < m_header.ncmds; ++i) {
- const lldb::offset_t load_cmd_offset = offset;
- if (m_data.GetU32(&offset, &encryption_cmd, 2) == NULL)
- break;
+ encryption_info_command encryption_cmd;
+ for (uint32_t i = 0; i < m_header.ncmds; ++i) {
+ const lldb::offset_t load_cmd_offset = offset;
+ if (m_data.GetU32(&offset, &encryption_cmd, 2) == NULL)
+ break;
- // LC_ENCRYPTION_INFO and LC_ENCRYPTION_INFO_64 have the same sizes for
- // the 3 fields we care about, so treat them the same.
- if (encryption_cmd.cmd == LC_ENCRYPTION_INFO ||
- encryption_cmd.cmd == LC_ENCRYPTION_INFO_64) {
- if (m_data.GetU32(&offset, &encryption_cmd.cryptoff, 3)) {
- if (encryption_cmd.cryptid != 0) {
- EncryptedFileRanges::Entry entry;
- entry.SetRangeBase(encryption_cmd.cryptoff);
- entry.SetByteSize(encryption_cmd.cryptsize);
- encrypted_file_ranges.Append(entry);
- }
+ // LC_ENCRYPTION_INFO and LC_ENCRYPTION_INFO_64 have the same sizes for the
+ // 3 fields we care about, so treat them the same.
+ if (encryption_cmd.cmd == LC_ENCRYPTION_INFO ||
+ encryption_cmd.cmd == LC_ENCRYPTION_INFO_64) {
+ if (m_data.GetU32(&offset, &encryption_cmd.cryptoff, 3)) {
+ if (encryption_cmd.cryptid != 0) {
+ EncryptedFileRanges::Entry entry;
+ entry.SetRangeBase(encryption_cmd.cryptoff);
+ entry.SetByteSize(encryption_cmd.cryptsize);
+ result.Append(entry);
}
}
- offset = load_cmd_offset + encryption_cmd.cmdsize;
}
+ offset = load_cmd_offset + encryption_cmd.cmdsize;
+ }
- bool section_file_addresses_changed = false;
+ return result;
+}
- offset = MachHeaderSizeFromMagic(m_header.magic);
+void ObjectFileMachO::SanitizeSegmentCommand(segment_command_64 &seg_cmd,
+ uint32_t cmd_idx) {
+ if (m_length == 0 || seg_cmd.filesize == 0)
+ return;
+
+ if (seg_cmd.fileoff > m_length) {
+ // We have a load command that says it extends past the end of the file.
+ // This is likely a corrupt file. We don't have any way to return an error
+ // condition here (this method was likely invoked from something like
+ // ObjectFile::GetSectionList()), so we just null out the section contents,
+ // and dump a message to stdout. The most common case here is core file
+ // debugging with a truncated file.
+ const char *lc_segment_name =
+ seg_cmd.cmd == LC_SEGMENT_64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
+ GetModule()->ReportWarning(
+ "load command %u %s has a fileoff (0x%" PRIx64
+ ") that extends beyond the end of the file (0x%" PRIx64
+ "), ignoring this section",
+ cmd_idx, lc_segment_name, seg_cmd.fileoff, m_length);
+
+ seg_cmd.fileoff = 0;
+ seg_cmd.filesize = 0;
+ }
- struct segment_command_64 load_cmd;
- for (i = 0; i < m_header.ncmds; ++i) {
- const lldb::offset_t load_cmd_offset = offset;
- if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
- break;
+ if (seg_cmd.fileoff + seg_cmd.filesize > m_length) {
+ // We have a load command that says it extends past the end of the file.
+ // This is likely a corrupt file. We don't have any way to return an error
+ // condition here (this method was likely invoked from something like
+ // ObjectFile::GetSectionList()), so we just null out the section contents,
+ // and dump a message to stdout. The most common case here is core file
+ // debugging with a truncated file.
+ const char *lc_segment_name =
+ seg_cmd.cmd == LC_SEGMENT_64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
+ GetModule()->ReportWarning(
+ "load command %u %s has a fileoff + filesize (0x%" PRIx64
+ ") that extends beyond the end of the file (0x%" PRIx64
+ "), the segment will be truncated to match",
+ cmd_idx, lc_segment_name, seg_cmd.fileoff + seg_cmd.filesize, m_length);
+
+ // Truncate the length
+ seg_cmd.filesize = m_length - seg_cmd.fileoff;
+ }
+}
- if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64) {
- if (m_data.GetU8(&offset, (uint8_t *)load_cmd.segname, 16)) {
- bool add_section = true;
- bool add_to_unified = true;
- ConstString const_segname(load_cmd.segname,
- std::min<size_t>(strlen(load_cmd.segname),
- sizeof(load_cmd.segname)));
-
- SectionSP unified_section_sp(
- unified_section_list.FindSectionByName(const_segname));
- if (is_dsym && unified_section_sp) {
- if (const_segname == GetSegmentNameLINKEDIT()) {
- // We need to keep the __LINKEDIT segment private to this object
- // file only
- add_to_unified = false;
- } else {
- // This is the dSYM file and this section has already been created
- // by
- // the object file, no need to create it.
- add_section = false;
- }
- }
- load_cmd.vmaddr = m_data.GetAddress(&offset);
- load_cmd.vmsize = m_data.GetAddress(&offset);
- load_cmd.fileoff = m_data.GetAddress(&offset);
- load_cmd.filesize = m_data.GetAddress(&offset);
- if (m_length != 0 && load_cmd.filesize != 0) {
- if (load_cmd.fileoff > m_length) {
- // We have a load command that says it extends past the end of the
- // file. This is likely
- // a corrupt file. We don't have any way to return an error
- // condition here (this method
- // was likely invoked from something like
- // ObjectFile::GetSectionList()) -- all we can do
- // is null out the SectionList vector and if a process has been
- // set up, dump a message
- // to stdout. The most common case here is core file debugging
- // with a truncated file.
- const char *lc_segment_name = load_cmd.cmd == LC_SEGMENT_64
- ? "LC_SEGMENT_64"
- : "LC_SEGMENT";
- module_sp->ReportWarning(
- "load command %u %s has a fileoff (0x%" PRIx64
- ") that extends beyond the end of the file (0x%" PRIx64
- "), ignoring this section",
- i, lc_segment_name, load_cmd.fileoff, m_length);
-
- load_cmd.fileoff = 0;
- load_cmd.filesize = 0;
- }
+static uint32_t GetSegmentPermissions(const segment_command_64 &seg_cmd) {
+ uint32_t result = 0;
+ if (seg_cmd.initprot & VM_PROT_READ)
+ result |= ePermissionsReadable;
+ if (seg_cmd.initprot & VM_PROT_WRITE)
+ result |= ePermissionsWritable;
+ if (seg_cmd.initprot & VM_PROT_EXECUTE)
+ result |= ePermissionsExecutable;
+ return result;
+}
- if (load_cmd.fileoff + load_cmd.filesize > m_length) {
- // We have a load command that says it extends past the end of the
- // file. This is likely
- // a corrupt file. We don't have any way to return an error
- // condition here (this method
- // was likely invoked from something like
- // ObjectFile::GetSectionList()) -- all we can do
- // is null out the SectionList vector and if a process has been
- // set up, dump a message
- // to stdout. The most common case here is core file debugging
- // with a truncated file.
- const char *lc_segment_name = load_cmd.cmd == LC_SEGMENT_64
- ? "LC_SEGMENT_64"
- : "LC_SEGMENT";
- GetModule()->ReportWarning(
- "load command %u %s has a fileoff + filesize (0x%" PRIx64
- ") that extends beyond the end of the file (0x%" PRIx64
- "), the segment will be truncated to match",
- i, lc_segment_name, load_cmd.fileoff + load_cmd.filesize,
- m_length);
-
- // Tuncase the length
- load_cmd.filesize = m_length - load_cmd.fileoff;
- }
- }
- if (m_data.GetU32(&offset, &load_cmd.maxprot, 4)) {
- uint32_t segment_permissions = 0;
- if (load_cmd.initprot & VM_PROT_READ)
- segment_permissions |= ePermissionsReadable;
- if (load_cmd.initprot & VM_PROT_WRITE)
- segment_permissions |= ePermissionsWritable;
- if (load_cmd.initprot & VM_PROT_EXECUTE)
- segment_permissions |= ePermissionsExecutable;
-
- const bool segment_is_encrypted =
- (load_cmd.flags & SG_PROTECTED_VERSION_1) != 0;
-
- // Keep a list of mach segments around in case we need to
- // get at data that isn't stored in the abstracted Sections.
- m_mach_segments.push_back(load_cmd);
-
- // Use a segment ID of the segment index shifted left by 8 so they
- // never conflict with any of the sections.
- SectionSP segment_sp;
- if (add_section && (const_segname || is_core)) {
- segment_sp.reset(new Section(
- module_sp, // Module to which this section belongs
- this, // Object file to which this sections belongs
- ++segID << 8, // Section ID is the 1 based segment index
- // shifted right by 8 bits as not to collide
- // with any of the 256 section IDs that are
- // possible
- const_segname, // Name of this section
- eSectionTypeContainer, // This section is a container of other
- // sections.
- load_cmd.vmaddr, // File VM address == addresses as they are
- // found in the object file
- load_cmd.vmsize, // VM size in bytes of this section
- load_cmd.fileoff, // Offset to the data for this section in
- // the file
- load_cmd.filesize, // Size in bytes of this section as found
- // in the file
- 0, // Segments have no alignment information
- load_cmd.flags)); // Flags for this section
-
- segment_sp->SetIsEncrypted(segment_is_encrypted);
- m_sections_ap->AddSection(segment_sp);
- segment_sp->SetPermissions(segment_permissions);
- if (add_to_unified)
- unified_section_list.AddSection(segment_sp);
- } else if (unified_section_sp) {
- if (is_dsym &&
- unified_section_sp->GetFileAddress() != load_cmd.vmaddr) {
- // Check to see if the module was read from memory?
- if (module_sp->GetObjectFile()->GetHeaderAddress().IsValid()) {
- // We have a module that is in memory and needs to have its
- // file address adjusted. We need to do this because when we
- // load a file from memory, its addresses will be slid
- // already,
- // yet the addresses in the new symbol file will still be
- // unslid.
- // Since everything is stored as section offset, this
- // shouldn't
- // cause any problems.
-
- // Make sure we've parsed the symbol table from the
- // ObjectFile before we go around changing its Sections.
- module_sp->GetObjectFile()->GetSymtab();
- // eh_frame would present the same problems but we parse that
- // on
- // a per-function basis as-needed so it's more difficult to
- // remove its use of the Sections. Realistically, the
- // environments
- // where this code path will be taken will not have eh_frame
- // sections.
-
- unified_section_sp->SetFileAddress(load_cmd.vmaddr);
-
- // Notify the module that the section addresses have been
- // changed once
- // we're done so any file-address caches can be updated.
- section_file_addresses_changed = true;
- }
- }
- m_sections_ap->AddSection(unified_section_sp);
- }
+static lldb::SectionType GetSectionType(uint32_t flags,
+ ConstString section_name) {
+
+ if (flags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS))
+ return eSectionTypeCode;
+
+ uint32_t mach_sect_type = flags & SECTION_TYPE;
+ static ConstString g_sect_name_objc_data("__objc_data");
+ static ConstString g_sect_name_objc_msgrefs("__objc_msgrefs");
+ static ConstString g_sect_name_objc_selrefs("__objc_selrefs");
+ static ConstString g_sect_name_objc_classrefs("__objc_classrefs");
+ static ConstString g_sect_name_objc_superrefs("__objc_superrefs");
+ static ConstString g_sect_name_objc_const("__objc_const");
+ static ConstString g_sect_name_objc_classlist("__objc_classlist");
+ static ConstString g_sect_name_cfstring("__cfstring");
+
+ static ConstString g_sect_name_dwarf_debug_abbrev("__debug_abbrev");
+ static ConstString g_sect_name_dwarf_debug_aranges("__debug_aranges");
+ static ConstString g_sect_name_dwarf_debug_frame("__debug_frame");
+ static ConstString g_sect_name_dwarf_debug_info("__debug_info");
+ static ConstString g_sect_name_dwarf_debug_line("__debug_line");
+ static ConstString g_sect_name_dwarf_debug_loc("__debug_loc");
+ static ConstString g_sect_name_dwarf_debug_macinfo("__debug_macinfo");
+ static ConstString g_sect_name_dwarf_debug_names("__debug_names");
+ static ConstString g_sect_name_dwarf_debug_pubnames("__debug_pubnames");
+ static ConstString g_sect_name_dwarf_debug_pubtypes("__debug_pubtypes");
+ static ConstString g_sect_name_dwarf_debug_ranges("__debug_ranges");
+ static ConstString g_sect_name_dwarf_debug_str("__debug_str");
+ static ConstString g_sect_name_dwarf_debug_types("__debug_types");
+ static ConstString g_sect_name_dwarf_apple_names("__apple_names");
+ static ConstString g_sect_name_dwarf_apple_types("__apple_types");
+ static ConstString g_sect_name_dwarf_apple_namespaces("__apple_namespac");
+ static ConstString g_sect_name_dwarf_apple_objc("__apple_objc");
+ static ConstString g_sect_name_eh_frame("__eh_frame");
+ static ConstString g_sect_name_compact_unwind("__unwind_info");
+ static ConstString g_sect_name_text("__text");
+ static ConstString g_sect_name_data("__data");
+ static ConstString g_sect_name_go_symtab("__gosymtab");
+
+ if (section_name == g_sect_name_dwarf_debug_abbrev)
+ return eSectionTypeDWARFDebugAbbrev;
+ if (section_name == g_sect_name_dwarf_debug_aranges)
+ return eSectionTypeDWARFDebugAranges;
+ if (section_name == g_sect_name_dwarf_debug_frame)
+ return eSectionTypeDWARFDebugFrame;
+ if (section_name == g_sect_name_dwarf_debug_info)
+ return eSectionTypeDWARFDebugInfo;
+ if (section_name == g_sect_name_dwarf_debug_line)
+ return eSectionTypeDWARFDebugLine;
+ if (section_name == g_sect_name_dwarf_debug_loc)
+ return eSectionTypeDWARFDebugLoc;
+ if (section_name == g_sect_name_dwarf_debug_macinfo)
+ return eSectionTypeDWARFDebugMacInfo;
+ if (section_name == g_sect_name_dwarf_debug_names)
+ return eSectionTypeDWARFDebugNames;
+ if (section_name == g_sect_name_dwarf_debug_pubnames)
+ return eSectionTypeDWARFDebugPubNames;
+ if (section_name == g_sect_name_dwarf_debug_pubtypes)
+ return eSectionTypeDWARFDebugPubTypes;
+ if (section_name == g_sect_name_dwarf_debug_ranges)
+ return eSectionTypeDWARFDebugRanges;
+ if (section_name == g_sect_name_dwarf_debug_str)
+ return eSectionTypeDWARFDebugStr;
+ if (section_name == g_sect_name_dwarf_debug_types)
+ return eSectionTypeDWARFDebugTypes;
+ if (section_name == g_sect_name_dwarf_apple_names)
+ return eSectionTypeDWARFAppleNames;
+ if (section_name == g_sect_name_dwarf_apple_types)
+ return eSectionTypeDWARFAppleTypes;
+ if (section_name == g_sect_name_dwarf_apple_namespaces)
+ return eSectionTypeDWARFAppleNamespaces;
+ if (section_name == g_sect_name_dwarf_apple_objc)
+ return eSectionTypeDWARFAppleObjC;
+ if (section_name == g_sect_name_objc_selrefs)
+ return eSectionTypeDataCStringPointers;
+ if (section_name == g_sect_name_objc_msgrefs)
+ return eSectionTypeDataObjCMessageRefs;
+ if (section_name == g_sect_name_eh_frame)
+ return eSectionTypeEHFrame;
+ if (section_name == g_sect_name_compact_unwind)
+ return eSectionTypeCompactUnwind;
+ if (section_name == g_sect_name_cfstring)
+ return eSectionTypeDataObjCCFStrings;
+ if (section_name == g_sect_name_go_symtab)
+ return eSectionTypeGoSymtab;
+ if (section_name == g_sect_name_objc_data ||
+ section_name == g_sect_name_objc_classrefs ||
+ section_name == g_sect_name_objc_superrefs ||
+ section_name == g_sect_name_objc_const ||
+ section_name == g_sect_name_objc_classlist) {
+ return eSectionTypeDataPointers;
+ }
- struct section_64 sect64;
- ::memset(&sect64, 0, sizeof(sect64));
- // Push a section into our mach sections for the section at
- // index zero (NO_SECT) if we don't have any mach sections yet...
- if (m_mach_sections.empty())
- m_mach_sections.push_back(sect64);
- uint32_t segment_sect_idx;
- const lldb::user_id_t first_segment_sectID = sectID + 1;
-
- const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8;
- for (segment_sect_idx = 0; segment_sect_idx < load_cmd.nsects;
- ++segment_sect_idx) {
- if (m_data.GetU8(&offset, (uint8_t *)sect64.sectname,
- sizeof(sect64.sectname)) == NULL)
- break;
- if (m_data.GetU8(&offset, (uint8_t *)sect64.segname,
- sizeof(sect64.segname)) == NULL)
- break;
- sect64.addr = m_data.GetAddress(&offset);
- sect64.size = m_data.GetAddress(&offset);
+ switch (mach_sect_type) {
+ // TODO: categorize sections by other flags for regular sections
+ case S_REGULAR:
+ if (section_name == g_sect_name_text)
+ return eSectionTypeCode;
+ if (section_name == g_sect_name_data)
+ return eSectionTypeData;
+ return eSectionTypeOther;
+ case S_ZEROFILL:
+ return eSectionTypeZeroFill;
+ case S_CSTRING_LITERALS: // section with only literal C strings
+ return eSectionTypeDataCString;
+ case S_4BYTE_LITERALS: // section with only 4 byte literals
+ return eSectionTypeData4;
+ case S_8BYTE_LITERALS: // section with only 8 byte literals
+ return eSectionTypeData8;
+ case S_LITERAL_POINTERS: // section with only pointers to literals
+ return eSectionTypeDataPointers;
+ case S_NON_LAZY_SYMBOL_POINTERS: // section with only non-lazy symbol pointers
+ return eSectionTypeDataPointers;
+ case S_LAZY_SYMBOL_POINTERS: // section with only lazy symbol pointers
+ return eSectionTypeDataPointers;
+ case S_SYMBOL_STUBS: // section with only symbol stubs, byte size of stub in
+ // the reserved2 field
+ return eSectionTypeCode;
+ case S_MOD_INIT_FUNC_POINTERS: // section with only function pointers for
+ // initialization
+ return eSectionTypeDataPointers;
+ case S_MOD_TERM_FUNC_POINTERS: // section with only function pointers for
+ // termination
+ return eSectionTypeDataPointers;
+ case S_COALESCED:
+ return eSectionTypeOther;
+ case S_GB_ZEROFILL:
+ return eSectionTypeZeroFill;
+ case S_INTERPOSING: // section with only pairs of function pointers for
+ // interposing
+ return eSectionTypeCode;
+ case S_16BYTE_LITERALS: // section with only 16 byte literals
+ return eSectionTypeData16;
+ case S_DTRACE_DOF:
+ return eSectionTypeDebug;
+ case S_LAZY_DYLIB_SYMBOL_POINTERS:
+ return eSectionTypeDataPointers;
+ default:
+ return eSectionTypeOther;
+ }
+}
- if (m_data.GetU32(&offset, &sect64.offset, num_u32s) == NULL)
- break;
+struct ObjectFileMachO::SegmentParsingContext {
+ const EncryptedFileRanges EncryptedRanges;
+ lldb_private::SectionList &UnifiedList;
+ uint32_t NextSegmentIdx = 0;
+ uint32_t NextSectionIdx = 0;
+ bool FileAddressesChanged = false;
- // Keep a list of mach sections around in case we need to
- // get at data that isn't stored in the abstracted Sections.
- m_mach_sections.push_back(sect64);
-
- if (add_section) {
- ConstString section_name(
- sect64.sectname, std::min<size_t>(strlen(sect64.sectname),
- sizeof(sect64.sectname)));
- if (!const_segname) {
- // We have a segment with no name so we need to conjure up
- // segments that correspond to the section's segname if there
- // isn't already such a section. If there is such a section,
- // we resize the section so that it spans all sections.
- // We also mark these sections as fake so address matches
- // don't
- // hit if they land in the gaps between the child sections.
- const_segname.SetTrimmedCStringWithLength(
- sect64.segname, sizeof(sect64.segname));
- segment_sp =
- unified_section_list.FindSectionByName(const_segname);
- if (segment_sp.get()) {
- Section *segment = segment_sp.get();
- // Grow the section size as needed.
- const lldb::addr_t sect64_min_addr = sect64.addr;
- const lldb::addr_t sect64_max_addr =
- sect64_min_addr + sect64.size;
- const lldb::addr_t curr_seg_byte_size =
- segment->GetByteSize();
- const lldb::addr_t curr_seg_min_addr =
- segment->GetFileAddress();
- const lldb::addr_t curr_seg_max_addr =
- curr_seg_min_addr + curr_seg_byte_size;
- if (sect64_min_addr >= curr_seg_min_addr) {
- const lldb::addr_t new_seg_byte_size =
- sect64_max_addr - curr_seg_min_addr;
- // Only grow the section size if needed
- if (new_seg_byte_size > curr_seg_byte_size)
- segment->SetByteSize(new_seg_byte_size);
- } else {
- // We need to change the base address of the segment and
- // adjust the child section offsets for all existing
- // children.
- const lldb::addr_t slide_amount =
- sect64_min_addr - curr_seg_min_addr;
- segment->Slide(slide_amount, false);
- segment->GetChildren().Slide(-slide_amount, false);
- segment->SetByteSize(curr_seg_max_addr - sect64_min_addr);
- }
+ SegmentParsingContext(EncryptedFileRanges EncryptedRanges,
+ lldb_private::SectionList &UnifiedList)
+ : EncryptedRanges(std::move(EncryptedRanges)), UnifiedList(UnifiedList) {}
+};
- // Grow the section size as needed.
- if (sect64.offset) {
- const lldb::addr_t segment_min_file_offset =
- segment->GetFileOffset();
- const lldb::addr_t segment_max_file_offset =
- segment_min_file_offset + segment->GetFileSize();
-
- const lldb::addr_t section_min_file_offset =
- sect64.offset;
- const lldb::addr_t section_max_file_offset =
- section_min_file_offset + sect64.size;
- const lldb::addr_t new_file_offset = std::min(
- section_min_file_offset, segment_min_file_offset);
- const lldb::addr_t new_file_size =
- std::max(section_max_file_offset,
- segment_max_file_offset) -
- new_file_offset;
- segment->SetFileOffset(new_file_offset);
- segment->SetFileSize(new_file_size);
- }
- } else {
- // Create a fake section for the section's named segment
- segment_sp.reset(new Section(
- segment_sp, // Parent section
- module_sp, // Module to which this section belongs
- this, // Object file to which this section belongs
- ++segID << 8, // Section ID is the 1 based segment index
- // shifted right by 8 bits as not to
- // collide with any of the 256 section IDs
- // that are possible
- const_segname, // Name of this section
- eSectionTypeContainer, // This section is a container of
- // other sections.
- sect64.addr, // File VM address == addresses as they are
- // found in the object file
- sect64.size, // VM size in bytes of this section
- sect64.offset, // Offset to the data for this section in
- // the file
- sect64.offset ? sect64.size : 0, // Size in bytes of
- // this section as
- // found in the file
- sect64.align,
- load_cmd.flags)); // Flags for this section
- segment_sp->SetIsFake(true);
- segment_sp->SetPermissions(segment_permissions);
- m_sections_ap->AddSection(segment_sp);
- if (add_to_unified)
- unified_section_list.AddSection(segment_sp);
- segment_sp->SetIsEncrypted(segment_is_encrypted);
- }
- }
- assert(segment_sp.get());
-
- lldb::SectionType sect_type = eSectionTypeOther;
-
- if (sect64.flags &
- (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS))
- sect_type = eSectionTypeCode;
- else {
- uint32_t mach_sect_type = sect64.flags & SECTION_TYPE;
- static ConstString g_sect_name_objc_data("__objc_data");
- static ConstString g_sect_name_objc_msgrefs("__objc_msgrefs");
- static ConstString g_sect_name_objc_selrefs("__objc_selrefs");
- static ConstString g_sect_name_objc_classrefs(
- "__objc_classrefs");
- static ConstString g_sect_name_objc_superrefs(
- "__objc_superrefs");
- static ConstString g_sect_name_objc_const("__objc_const");
- static ConstString g_sect_name_objc_classlist(
- "__objc_classlist");
- static ConstString g_sect_name_cfstring("__cfstring");
-
- static ConstString g_sect_name_dwarf_debug_abbrev(
- "__debug_abbrev");
- static ConstString g_sect_name_dwarf_debug_aranges(
- "__debug_aranges");
- static ConstString g_sect_name_dwarf_debug_frame(
- "__debug_frame");
- static ConstString g_sect_name_dwarf_debug_info(
- "__debug_info");
- static ConstString g_sect_name_dwarf_debug_line(
- "__debug_line");
- static ConstString g_sect_name_dwarf_debug_loc("__debug_loc");
- static ConstString g_sect_name_dwarf_debug_macinfo(
- "__debug_macinfo");
- static ConstString g_sect_name_dwarf_debug_pubnames(
- "__debug_pubnames");
- static ConstString g_sect_name_dwarf_debug_pubtypes(
- "__debug_pubtypes");
- static ConstString g_sect_name_dwarf_debug_ranges(
- "__debug_ranges");
- static ConstString g_sect_name_dwarf_debug_str("__debug_str");
- static ConstString g_sect_name_dwarf_apple_names(
- "__apple_names");
- static ConstString g_sect_name_dwarf_apple_types(
- "__apple_types");
- static ConstString g_sect_name_dwarf_apple_namespaces(
- "__apple_namespac");
- static ConstString g_sect_name_dwarf_apple_objc(
- "__apple_objc");
- static ConstString g_sect_name_eh_frame("__eh_frame");
- static ConstString g_sect_name_compact_unwind(
- "__unwind_info");
- static ConstString g_sect_name_text("__text");
- static ConstString g_sect_name_data("__data");
- static ConstString g_sect_name_go_symtab("__gosymtab");
-
- if (section_name == g_sect_name_dwarf_debug_abbrev)
- sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (section_name == g_sect_name_dwarf_debug_aranges)
- sect_type = eSectionTypeDWARFDebugAranges;
- else if (section_name == g_sect_name_dwarf_debug_frame)
- sect_type = eSectionTypeDWARFDebugFrame;
- else if (section_name == g_sect_name_dwarf_debug_info)
- sect_type = eSectionTypeDWARFDebugInfo;
- else if (section_name == g_sect_name_dwarf_debug_line)
- sect_type = eSectionTypeDWARFDebugLine;
- else if (section_name == g_sect_name_dwarf_debug_loc)
- sect_type = eSectionTypeDWARFDebugLoc;
- else if (section_name == g_sect_name_dwarf_debug_macinfo)
- sect_type = eSectionTypeDWARFDebugMacInfo;
- else if (section_name == g_sect_name_dwarf_debug_pubnames)
- sect_type = eSectionTypeDWARFDebugPubNames;
- else if (section_name == g_sect_name_dwarf_debug_pubtypes)
- sect_type = eSectionTypeDWARFDebugPubTypes;
- else if (section_name == g_sect_name_dwarf_debug_ranges)
- sect_type = eSectionTypeDWARFDebugRanges;
- else if (section_name == g_sect_name_dwarf_debug_str)
- sect_type = eSectionTypeDWARFDebugStr;
- else if (section_name == g_sect_name_dwarf_apple_names)
- sect_type = eSectionTypeDWARFAppleNames;
- else if (section_name == g_sect_name_dwarf_apple_types)
- sect_type = eSectionTypeDWARFAppleTypes;
- else if (section_name == g_sect_name_dwarf_apple_namespaces)
- sect_type = eSectionTypeDWARFAppleNamespaces;
- else if (section_name == g_sect_name_dwarf_apple_objc)
- sect_type = eSectionTypeDWARFAppleObjC;
- else if (section_name == g_sect_name_objc_selrefs)
- sect_type = eSectionTypeDataCStringPointers;
- else if (section_name == g_sect_name_objc_msgrefs)
- sect_type = eSectionTypeDataObjCMessageRefs;
- else if (section_name == g_sect_name_eh_frame)
- sect_type = eSectionTypeEHFrame;
- else if (section_name == g_sect_name_compact_unwind)
- sect_type = eSectionTypeCompactUnwind;
- else if (section_name == g_sect_name_cfstring)
- sect_type = eSectionTypeDataObjCCFStrings;
- else if (section_name == g_sect_name_go_symtab)
- sect_type = eSectionTypeGoSymtab;
- else if (section_name == g_sect_name_objc_data ||
- section_name == g_sect_name_objc_classrefs ||
- section_name == g_sect_name_objc_superrefs ||
- section_name == g_sect_name_objc_const ||
- section_name == g_sect_name_objc_classlist) {
- sect_type = eSectionTypeDataPointers;
- }
+void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_,
+ lldb::offset_t offset,
+ uint32_t cmd_idx,
+ SegmentParsingContext &context) {
+ segment_command_64 load_cmd;
+ memcpy(&load_cmd, &load_cmd_, sizeof(load_cmd_));
- if (sect_type == eSectionTypeOther) {
- switch (mach_sect_type) {
- // TODO: categorize sections by other flags for regular
- // sections
- case S_REGULAR:
- if (section_name == g_sect_name_text)
- sect_type = eSectionTypeCode;
- else if (section_name == g_sect_name_data)
- sect_type = eSectionTypeData;
- else
- sect_type = eSectionTypeOther;
- break;
- case S_ZEROFILL:
- sect_type = eSectionTypeZeroFill;
- break;
- case S_CSTRING_LITERALS:
- sect_type = eSectionTypeDataCString;
- break; // section with only literal C strings
- case S_4BYTE_LITERALS:
- sect_type = eSectionTypeData4;
- break; // section with only 4 byte literals
- case S_8BYTE_LITERALS:
- sect_type = eSectionTypeData8;
- break; // section with only 8 byte literals
- case S_LITERAL_POINTERS:
- sect_type = eSectionTypeDataPointers;
- break; // section with only pointers to literals
- case S_NON_LAZY_SYMBOL_POINTERS:
- sect_type = eSectionTypeDataPointers;
- break; // section with only non-lazy symbol pointers
- case S_LAZY_SYMBOL_POINTERS:
- sect_type = eSectionTypeDataPointers;
- break; // section with only lazy symbol pointers
- case S_SYMBOL_STUBS:
- sect_type = eSectionTypeCode;
- break; // section with only symbol stubs, byte size of
- // stub in the reserved2 field
- case S_MOD_INIT_FUNC_POINTERS:
- sect_type = eSectionTypeDataPointers;
- break; // section with only function pointers for
- // initialization
- case S_MOD_TERM_FUNC_POINTERS:
- sect_type = eSectionTypeDataPointers;
- break; // section with only function pointers for
- // termination
- case S_COALESCED:
- sect_type = eSectionTypeOther;
- break;
- case S_GB_ZEROFILL:
- sect_type = eSectionTypeZeroFill;
- break;
- case S_INTERPOSING:
- sect_type = eSectionTypeCode;
- break; // section with only pairs of function pointers for
- // interposing
- case S_16BYTE_LITERALS:
- sect_type = eSectionTypeData16;
- break; // section with only 16 byte literals
- case S_DTRACE_DOF:
- sect_type = eSectionTypeDebug;
- break;
- case S_LAZY_DYLIB_SYMBOL_POINTERS:
- sect_type = eSectionTypeDataPointers;
- break;
- default:
- break;
- }
- }
- }
+ if (!m_data.GetU8(&offset, (uint8_t *)load_cmd.segname, 16))
+ return;
- SectionSP section_sp(new Section(
- segment_sp, module_sp, this, ++sectID, section_name,
- sect_type, sect64.addr - segment_sp->GetFileAddress(),
- sect64.size, sect64.offset,
- sect64.offset == 0 ? 0 : sect64.size, sect64.align,
- sect64.flags));
- // Set the section to be encrypted to match the segment
-
- bool section_is_encrypted = false;
- if (!segment_is_encrypted && load_cmd.filesize != 0)
- section_is_encrypted =
- encrypted_file_ranges.FindEntryThatContains(
- sect64.offset) != NULL;
-
- section_sp->SetIsEncrypted(segment_is_encrypted ||
- section_is_encrypted);
- section_sp->SetPermissions(segment_permissions);
- segment_sp->GetChildren().AddSection(section_sp);
-
- if (segment_sp->IsFake()) {
- segment_sp.reset();
- const_segname.Clear();
- }
- }
- }
- if (segment_sp && is_dsym) {
- if (first_segment_sectID <= sectID) {
- lldb::user_id_t sect_uid;
- for (sect_uid = first_segment_sectID; sect_uid <= sectID;
- ++sect_uid) {
- SectionSP curr_section_sp(
- segment_sp->GetChildren().FindSectionByID(sect_uid));
- SectionSP next_section_sp;
- if (sect_uid + 1 <= sectID)
- next_section_sp =
- segment_sp->GetChildren().FindSectionByID(sect_uid + 1);
-
- if (curr_section_sp.get()) {
- if (curr_section_sp->GetByteSize() == 0) {
- if (next_section_sp.get() != NULL)
- curr_section_sp->SetByteSize(
- next_section_sp->GetFileAddress() -
- curr_section_sp->GetFileAddress());
- else
- curr_section_sp->SetByteSize(load_cmd.vmsize);
- }
- }
- }
- }
- }
+ ModuleSP module_sp = GetModule();
+ const bool is_core = GetType() == eTypeCoreFile;
+ const bool is_dsym = (m_header.filetype == MH_DSYM);
+ bool add_section = true;
+ bool add_to_unified = true;
+ ConstString const_segname(
+ load_cmd.segname,
+ std::min<size_t>(strlen(load_cmd.segname), sizeof(load_cmd.segname)));
+
+ SectionSP unified_section_sp(
+ context.UnifiedList.FindSectionByName(const_segname));
+ if (is_dsym && unified_section_sp) {
+ if (const_segname == GetSegmentNameLINKEDIT()) {
+ // We need to keep the __LINKEDIT segment private to this object file
+ // only
+ add_to_unified = false;
+ } else {
+ // This is the dSYM file and this section has already been created by the
+ // object file, no need to create it.
+ add_section = false;
+ }
+ }
+ load_cmd.vmaddr = m_data.GetAddress(&offset);
+ load_cmd.vmsize = m_data.GetAddress(&offset);
+ load_cmd.fileoff = m_data.GetAddress(&offset);
+ load_cmd.filesize = m_data.GetAddress(&offset);
+ if (!m_data.GetU32(&offset, &load_cmd.maxprot, 4))
+ return;
+
+ SanitizeSegmentCommand(load_cmd, cmd_idx);
+
+ const uint32_t segment_permissions = GetSegmentPermissions(load_cmd);
+ const bool segment_is_encrypted =
+ (load_cmd.flags & SG_PROTECTED_VERSION_1) != 0;
+
+ // Keep a list of mach segments around in case we need to get at data that
+ // isn't stored in the abstracted Sections.
+ m_mach_segments.push_back(load_cmd);
+
+ // Use a segment ID of the segment index shifted left by 8 so they never
+ // conflict with any of the sections.
+ SectionSP segment_sp;
+ if (add_section && (const_segname || is_core)) {
+ segment_sp.reset(new Section(
+ module_sp, // Module to which this section belongs
+ this, // Object file to which this sections belongs
+ ++context.NextSegmentIdx
+ << 8, // Section ID is the 1 based segment index
+ // shifted right by 8 bits as not to collide with any of the 256
+ // section IDs that are possible
+ const_segname, // Name of this section
+ eSectionTypeContainer, // This section is a container of other
+ // sections.
+ load_cmd.vmaddr, // File VM address == addresses as they are
+ // found in the object file
+ load_cmd.vmsize, // VM size in bytes of this section
+ load_cmd.fileoff, // Offset to the data for this section in
+ // the file
+ load_cmd.filesize, // Size in bytes of this section as found
+ // in the file
+ 0, // Segments have no alignment information
+ load_cmd.flags)); // Flags for this section
+
+ segment_sp->SetIsEncrypted(segment_is_encrypted);
+ m_sections_ap->AddSection(segment_sp);
+ segment_sp->SetPermissions(segment_permissions);
+ if (add_to_unified)
+ context.UnifiedList.AddSection(segment_sp);
+ } else if (unified_section_sp) {
+ if (is_dsym && unified_section_sp->GetFileAddress() != load_cmd.vmaddr) {
+ // Check to see if the module was read from memory?
+ if (module_sp->GetObjectFile()->GetHeaderAddress().IsValid()) {
+ // We have a module that is in memory and needs to have its file
+ // address adjusted. We need to do this because when we load a file
+ // from memory, its addresses will be slid already, yet the addresses
+ // in the new symbol file will still be unslid. Since everything is
+ // stored as section offset, this shouldn't cause any problems.
+
+ // Make sure we've parsed the symbol table from the ObjectFile before
+ // we go around changing its Sections.
+ module_sp->GetObjectFile()->GetSymtab();
+ // eh_frame would present the same problems but we parse that on a per-
+ // function basis as-needed so it's more difficult to remove its use of
+ // the Sections. Realistically, the environments where this code path
+ // will be taken will not have eh_frame sections.
+
+ unified_section_sp->SetFileAddress(load_cmd.vmaddr);
+
+ // Notify the module that the section addresses have been changed once
+ // we're done so any file-address caches can be updated.
+ context.FileAddressesChanged = true;
+ }
+ }
+ m_sections_ap->AddSection(unified_section_sp);
+ }
+
+ struct section_64 sect64;
+ ::memset(&sect64, 0, sizeof(sect64));
+ // Push a section into our mach sections for the section at index zero
+ // (NO_SECT) if we don't have any mach sections yet...
+ if (m_mach_sections.empty())
+ m_mach_sections.push_back(sect64);
+ uint32_t segment_sect_idx;
+ const lldb::user_id_t first_segment_sectID = context.NextSectionIdx + 1;
+
+ const uint32_t num_u32s = load_cmd.cmd == LC_SEGMENT ? 7 : 8;
+ for (segment_sect_idx = 0; segment_sect_idx < load_cmd.nsects;
+ ++segment_sect_idx) {
+ if (m_data.GetU8(&offset, (uint8_t *)sect64.sectname,
+ sizeof(sect64.sectname)) == NULL)
+ break;
+ if (m_data.GetU8(&offset, (uint8_t *)sect64.segname,
+ sizeof(sect64.segname)) == NULL)
+ break;
+ sect64.addr = m_data.GetAddress(&offset);
+ sect64.size = m_data.GetAddress(&offset);
+
+ if (m_data.GetU32(&offset, &sect64.offset, num_u32s) == NULL)
+ break;
+
+ // Keep a list of mach sections around in case we need to get at data that
+ // isn't stored in the abstracted Sections.
+ m_mach_sections.push_back(sect64);
+
+ if (add_section) {
+ ConstString section_name(
+ sect64.sectname,
+ std::min<size_t>(strlen(sect64.sectname), sizeof(sect64.sectname)));
+ if (!const_segname) {
+ // We have a segment with no name so we need to conjure up segments
+ // that correspond to the section's segname if there isn't already such
+ // a section. If there is such a section, we resize the section so that
+ // it spans all sections. We also mark these sections as fake so
+ // address matches don't hit if they land in the gaps between the child
+ // sections.
+ const_segname.SetTrimmedCStringWithLength(sect64.segname,
+ sizeof(sect64.segname));
+ segment_sp = context.UnifiedList.FindSectionByName(const_segname);
+ if (segment_sp.get()) {
+ Section *segment = segment_sp.get();
+ // Grow the section size as needed.
+ const lldb::addr_t sect64_min_addr = sect64.addr;
+ const lldb::addr_t sect64_max_addr = sect64_min_addr + sect64.size;
+ const lldb::addr_t curr_seg_byte_size = segment->GetByteSize();
+ const lldb::addr_t curr_seg_min_addr = segment->GetFileAddress();
+ const lldb::addr_t curr_seg_max_addr =
+ curr_seg_min_addr + curr_seg_byte_size;
+ if (sect64_min_addr >= curr_seg_min_addr) {
+ const lldb::addr_t new_seg_byte_size =
+ sect64_max_addr - curr_seg_min_addr;
+ // Only grow the section size if needed
+ if (new_seg_byte_size > curr_seg_byte_size)
+ segment->SetByteSize(new_seg_byte_size);
+ } else {
+ // We need to change the base address of the segment and adjust the
+ // child section offsets for all existing children.
+ const lldb::addr_t slide_amount =
+ sect64_min_addr - curr_seg_min_addr;
+ segment->Slide(slide_amount, false);
+ segment->GetChildren().Slide(-slide_amount, false);
+ segment->SetByteSize(curr_seg_max_addr - sect64_min_addr);
}
+
+ // Grow the section size as needed.
+ if (sect64.offset) {
+ const lldb::addr_t segment_min_file_offset =
+ segment->GetFileOffset();
+ const lldb::addr_t segment_max_file_offset =
+ segment_min_file_offset + segment->GetFileSize();
+
+ const lldb::addr_t section_min_file_offset = sect64.offset;
+ const lldb::addr_t section_max_file_offset =
+ section_min_file_offset + sect64.size;
+ const lldb::addr_t new_file_offset =
+ std::min(section_min_file_offset, segment_min_file_offset);
+ const lldb::addr_t new_file_size =
+ std::max(section_max_file_offset, segment_max_file_offset) -
+ new_file_offset;
+ segment->SetFileOffset(new_file_offset);
+ segment->SetFileSize(new_file_size);
+ }
+ } else {
+ // Create a fake section for the section's named segment
+ segment_sp.reset(new Section(
+ segment_sp, // Parent section
+ module_sp, // Module to which this section belongs
+ this, // Object file to which this section belongs
+ ++context.NextSegmentIdx
+ << 8, // Section ID is the 1 based segment index
+ // shifted right by 8 bits as not to
+ // collide with any of the 256 section IDs
+ // that are possible
+ const_segname, // Name of this section
+ eSectionTypeContainer, // This section is a container of
+ // other sections.
+ sect64.addr, // File VM address == addresses as they are
+ // found in the object file
+ sect64.size, // VM size in bytes of this section
+ sect64.offset, // Offset to the data for this section in
+ // the file
+ sect64.offset ? sect64.size : 0, // Size in bytes of
+ // this section as
+ // found in the file
+ sect64.align,
+ load_cmd.flags)); // Flags for this section
+ segment_sp->SetIsFake(true);
+ segment_sp->SetPermissions(segment_permissions);
+ m_sections_ap->AddSection(segment_sp);
+ if (add_to_unified)
+ context.UnifiedList.AddSection(segment_sp);
+ segment_sp->SetIsEncrypted(segment_is_encrypted);
}
- } else if (load_cmd.cmd == LC_DYSYMTAB) {
- m_dysymtab.cmd = load_cmd.cmd;
- m_dysymtab.cmdsize = load_cmd.cmdsize;
- m_data.GetU32(&offset, &m_dysymtab.ilocalsym,
- (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2);
}
+ assert(segment_sp.get());
- offset = load_cmd_offset + load_cmd.cmdsize;
- }
+ lldb::SectionType sect_type = GetSectionType(sect64.flags, section_name);
+
+ SectionSP section_sp(new Section(
+ segment_sp, module_sp, this, ++context.NextSectionIdx, section_name,
+ sect_type, sect64.addr - segment_sp->GetFileAddress(), sect64.size,
+ sect64.offset, sect64.offset == 0 ? 0 : sect64.size, sect64.align,
+ sect64.flags));
+ // Set the section to be encrypted to match the segment
+
+ bool section_is_encrypted = false;
+ if (!segment_is_encrypted && load_cmd.filesize != 0)
+ section_is_encrypted = context.EncryptedRanges.FindEntryThatContains(
+ sect64.offset) != NULL;
+
+ section_sp->SetIsEncrypted(segment_is_encrypted || section_is_encrypted);
+ section_sp->SetPermissions(segment_permissions);
+ segment_sp->GetChildren().AddSection(section_sp);
- if (section_file_addresses_changed && module_sp.get()) {
- module_sp->SectionFileAddressesChanged();
+ if (segment_sp->IsFake()) {
+ segment_sp.reset();
+ const_segname.Clear();
+ }
+ }
+ }
+ if (segment_sp && is_dsym) {
+ if (first_segment_sectID <= context.NextSectionIdx) {
+ lldb::user_id_t sect_uid;
+ for (sect_uid = first_segment_sectID; sect_uid <= context.NextSectionIdx;
+ ++sect_uid) {
+ SectionSP curr_section_sp(
+ segment_sp->GetChildren().FindSectionByID(sect_uid));
+ SectionSP next_section_sp;
+ if (sect_uid + 1 <= context.NextSectionIdx)
+ next_section_sp =
+ segment_sp->GetChildren().FindSectionByID(sect_uid + 1);
+
+ if (curr_section_sp.get()) {
+ if (curr_section_sp->GetByteSize() == 0) {
+ if (next_section_sp.get() != NULL)
+ curr_section_sp->SetByteSize(next_section_sp->GetFileAddress() -
+ curr_section_sp->GetFileAddress());
+ else
+ curr_section_sp->SetByteSize(load_cmd.vmsize);
+ }
+ }
+ }
}
}
}
+void ObjectFileMachO::ProcessDysymtabCommand(const load_command &load_cmd,
+ lldb::offset_t offset) {
+ m_dysymtab.cmd = load_cmd.cmd;
+ m_dysymtab.cmdsize = load_cmd.cmdsize;
+ m_data.GetU32(&offset, &m_dysymtab.ilocalsym,
+ (sizeof(m_dysymtab) / sizeof(uint32_t)) - 2);
+}
+
+void ObjectFileMachO::CreateSections(SectionList &unified_section_list) {
+ if (m_sections_ap)
+ return;
+
+ m_sections_ap.reset(new SectionList());
+
+ lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
+ // bool dump_sections = false;
+ ModuleSP module_sp(GetModule());
+
+ offset = MachHeaderSizeFromMagic(m_header.magic);
+
+ SegmentParsingContext context(GetEncryptedFileRanges(), unified_section_list);
+ struct load_command load_cmd;
+ for (uint32_t i = 0; i < m_header.ncmds; ++i) {
+ const lldb::offset_t load_cmd_offset = offset;
+ if (m_data.GetU32(&offset, &load_cmd, 2) == NULL)
+ break;
+
+ if (load_cmd.cmd == LC_SEGMENT || load_cmd.cmd == LC_SEGMENT_64)
+ ProcessSegmentCommand(load_cmd, offset, i, context);
+ else if (load_cmd.cmd == LC_DYSYMTAB)
+ ProcessDysymtabCommand(load_cmd, offset);
+
+ offset = load_cmd_offset + load_cmd.cmdsize;
+ }
+
+ if (context.FileAddressesChanged && module_sp)
+ module_sp->SectionFileAddressesChanged();
+}
+
class MachSymtabSectionInfo {
public:
MachSymtabSectionInfo(SectionList *section_list)
: m_section_list(section_list), m_section_infos() {
- // Get the number of sections down to a depth of 1 to include
- // all segments and their sections, but no other sections that
- // may be added for debug map or
+ // Get the number of sections down to a depth of 1 to include all segments
+ // and their sections, but no other sections that may be added for debug
+ // map or
m_section_infos.resize(section_list->GetNumSections(1));
}
@@ -1956,9 +1935,9 @@ public:
} else if (m_section_infos[n_sect].vm_range.GetByteSize() == 0 &&
m_section_infos[n_sect].vm_range.GetBaseAddress() ==
file_addr) {
- // Symbol is in section with zero size, but has the same start
- // address as the section. This can happen with linker symbols
- // (symbols that start with the letter 'l' or 'L'.
+ // Symbol is in section with zero size, but has the same start address
+ // as the section. This can happen with linker symbols (symbols that
+ // start with the letter 'l' or 'L'.
return m_section_infos[n_sect].section_sp;
}
}
@@ -2108,10 +2087,13 @@ UUID ObjectFileMachO::GetSharedCacheUUID(FileSpec dyld_shared_cache,
version_str[6] = '\0';
if (strcmp(version_str, "dyld_v") == 0) {
offset = offsetof(struct lldb_copy_dyld_cache_header_v1, uuid);
- uint8_t uuid_bytes[sizeof(uuid_t)];
- memcpy(uuid_bytes, dsc_header_data.GetData(&offset, sizeof(uuid_t)),
- sizeof(uuid_t));
- dsc_uuid.SetBytes(uuid_bytes);
+ dsc_uuid = UUID::fromOptionalData(
+ dsc_header_data.GetData(&offset, sizeof(uuid_t)), sizeof(uuid_t));
+ }
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS));
+ if (log && dsc_uuid.IsValid()) {
+ log->Printf("Shared cache %s has UUID %s", dyld_shared_cache.GetPath().c_str(),
+ dsc_uuid.GetAsString().c_str());
}
return dsc_uuid;
}
@@ -2267,10 +2249,9 @@ size_t ObjectFileMachO::ParseSymtab() {
linkedit_section_sp->GetLoadBaseAddress(&target);
if (linkedit_load_addr == LLDB_INVALID_ADDRESS) {
// We might be trying to access the symbol table before the
- // __LINKEDIT's load
- // address has been set in the target. We can't fail to read the
- // symbol table,
- // so calculate the right address manually
+ // __LINKEDIT's load address has been set in the target. We can't
+ // fail to read the symbol table, so calculate the right address
+ // manually
linkedit_load_addr = CalculateSectionLoadAddressForMemoryImage(
m_memory_addr, GetMachHeaderSection(), linkedit_section_sp.get());
}
@@ -2291,8 +2272,8 @@ size_t ObjectFileMachO::ParseSymtab() {
process->GetAddressByteSize() == sizeof(void *)) {
// This mach-o memory file is in the dyld shared cache. If this
// program is not remote and this is iOS, then this process will
- // share the same shared cache as the process we are debugging and
- // we can read the entire __LINKEDIT from the address space in this
+ // share the same shared cache as the process we are debugging and we
+ // can read the entire __LINKEDIT from the address space in this
// process. This is a needed optimization that is used for local iOS
// debugging only since all shared libraries in the shared cache do
// not have corresponding files that exist in the file system of the
@@ -2301,22 +2282,21 @@ size_t ObjectFileMachO::ParseSymtab() {
// string tables from all of the __LINKEDIT sections from the shared
// libraries in the shared cache have been merged into a single large
// symbol and string table. Reading all of this symbol and string
- // table
- // data across can slow down debug launch times, so we optimize this
- // by
- // reading the memory for the __LINKEDIT section from this process.
-
- UUID lldb_shared_cache(GetLLDBSharedCacheUUID());
- UUID process_shared_cache(GetProcessSharedCacheUUID(process));
+ // table data across can slow down debug launch times, so we optimize
+ // this by reading the memory for the __LINKEDIT section from this
+ // process.
+
+ UUID lldb_shared_cache;
+ addr_t lldb_shared_cache_addr;
+ GetLLDBSharedCacheUUID (lldb_shared_cache_addr, lldb_shared_cache);
+ UUID process_shared_cache;
+ addr_t process_shared_cache_addr;
+ GetProcessSharedCacheUUID(process, process_shared_cache_addr, process_shared_cache);
bool use_lldb_cache = true;
if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() &&
- lldb_shared_cache != process_shared_cache) {
+ (lldb_shared_cache != process_shared_cache
+ || process_shared_cache_addr != lldb_shared_cache_addr)) {
use_lldb_cache = false;
- ModuleSP module_sp(GetModule());
- if (module_sp)
- module_sp->ReportWarning("shared cache in process does not match "
- "lldb's own shared cache, startup will "
- "be slow.");
}
PlatformSP platform_sp(target.GetPlatform());
@@ -2340,10 +2320,9 @@ size_t ObjectFileMachO::ParseSymtab() {
if (!data_was_read) {
// Always load dyld - the dynamic linker - from memory if we didn't
- // find a binary anywhere else.
- // lldb will not register dylib/framework/bundle loads/unloads if we
- // don't have the dyld symbols,
- // we force dyld to load from memory despite the user's
+ // find a binary anywhere else. lldb will not register
+ // dylib/framework/bundle loads/unloads if we don't have the dyld
+ // symbols, we force dyld to load from memory despite the user's
// target.memory-module-load-level setting.
if (memory_module_load_level == eMemoryModuleLoadLevelComplete ||
m_header.filetype == llvm::MachO::MH_DYLINKER) {
@@ -2353,10 +2332,9 @@ size_t ObjectFileMachO::ParseSymtab() {
nlist_data.SetData(nlist_data_sp, 0,
nlist_data_sp->GetByteSize());
// Load strings individually from memory when loading from memory
- // since shared cache
- // string tables contain strings for all symbols from all shared
- // cached libraries
- // DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr,
+ // since shared cache string tables contain strings for all symbols
+ // from all shared cached libraries DataBufferSP strtab_data_sp
+ // (ReadMemory (process_sp, strtab_addr,
// strtab_data_byte_size));
// if (strtab_data_sp)
// strtab_data.SetData (strtab_data_sp, 0,
@@ -2460,11 +2438,9 @@ size_t ObjectFileMachO::ParseSymtab() {
const bool is_arm = (m_header.cputype == llvm::MachO::CPU_TYPE_ARM);
// lldb works best if it knows the start address of all functions in a
- // module.
- // Linker symbols or debug info are normally the best source of information
- // for start addr / size but
- // they may be stripped in a released binary.
- // Two additional sources of information exist in Mach-O binaries:
+ // module. Linker symbols or debug info are normally the best source of
+ // information for start addr / size but they may be stripped in a released
+ // binary. Two additional sources of information exist in Mach-O binaries:
// LC_FUNCTION_STARTS - a list of ULEB128 encoded offsets of each
// function's start address in the
// binary, relative to the text section.
@@ -2489,12 +2465,10 @@ size_t ObjectFileMachO::ParseSymtab() {
}
} else {
// If m_type is eTypeDebugInfo, then this is a dSYM - it will have the
- // load command claiming an eh_frame
- // but it doesn't actually have the eh_frame content. And if we have a
- // dSYM, we don't need to do any
- // of this fill-in-the-missing-symbols works anyway - the debug info
- // should give us all the functions in
- // the module.
+ // load command claiming an eh_frame but it doesn't actually have the
+ // eh_frame content. And if we have a dSYM, we don't need to do any of
+ // this fill-in-the-missing-symbols works anyway - the debug info should
+ // give us all the functions in the module.
if (text_section_sp.get() && eh_frame_section_sp.get() &&
m_type != eTypeDebugInfo) {
DWARFCallFrameInfo eh_frame(*this, eh_frame_section_sp,
@@ -2518,18 +2492,14 @@ size_t ObjectFileMachO::ParseSymtab() {
const size_t function_starts_count = function_starts.GetSize();
// For user process binaries (executables, dylibs, frameworks, bundles), if
- // we don't have
- // LC_FUNCTION_STARTS/eh_frame section in this binary, we're going to assume
- // the binary
- // has been stripped. Don't allow assembly language instruction emulation
- // because we don't
- // know proper function start boundaries.
+ // we don't have LC_FUNCTION_STARTS/eh_frame section in this binary, we're
+ // going to assume the binary has been stripped. Don't allow assembly
+ // language instruction emulation because we don't know proper function
+ // start boundaries.
//
// For all other types of binaries (kernels, stand-alone bare board
- // binaries, kexts), they
- // may not have LC_FUNCTION_STARTS / eh_frame sections - we should not make
- // any assumptions
- // about them based on that.
+ // binaries, kexts), they may not have LC_FUNCTION_STARTS / eh_frame
+ // sections - we should not make any assumptions about them based on that.
if (function_starts_count == 0 && CalculateStrata() == eStrataUser) {
m_allow_assembly_emulation_unwind_plans = false;
Log *unwind_or_symbol_log(lldb_private::GetLogIfAnyCategoriesSet(
@@ -2561,8 +2531,8 @@ size_t ObjectFileMachO::ParseSymtab() {
ValueToSymbolIndexMap N_FUN_addr_to_sym_idx;
ValueToSymbolIndexMap N_STSYM_addr_to_sym_idx;
ConstNameToSymbolIndexMap N_GSYM_name_to_sym_idx;
- // Any symbols that get merged into another will get an entry
- // in this map so we know
+ // Any symbols that get merged into another will get an entry in this map
+ // so we know
NListIndexToSymbolIndexMap m_nlist_idx_to_sym_idx;
uint32_t nlist_idx = 0;
Symbol *symbol_ptr = NULL;
@@ -2601,21 +2571,18 @@ size_t ObjectFileMachO::ParseSymtab() {
(defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
// Some recent builds of the dyld_shared_cache (hereafter: DSC) have been
- // optimized by moving LOCAL
- // symbols out of the memory mapped portion of the DSC. The symbol
- // information has all been retained,
- // but it isn't available in the normal nlist data. However, there *are*
- // duplicate entries of *some*
+ // optimized by moving LOCAL symbols out of the memory mapped portion of
+ // the DSC. The symbol information has all been retained, but it isn't
+ // available in the normal nlist data. However, there *are* duplicate
+ // entries of *some*
// LOCAL symbols in the normal nlist data. To handle this situation
// correctly, we must first attempt
// to parse any DSC unmapped symbol information. If we find any, we set a
- // flag that tells the normal
- // nlist parser to ignore all LOCAL symbols.
+ // flag that tells the normal nlist parser to ignore all LOCAL symbols.
if (m_header.flags & 0x80000000u) {
- // Before we can start mapping the DSC, we need to make certain the target
- // process is actually
- // using the cache we can find.
+ // Before we can start mapping the DSC, we need to make certain the
+ // target process is actually using the cache we can find.
// Next we need to determine the correct path for the dyld shared cache.
@@ -2644,14 +2611,15 @@ size_t ObjectFileMachO::ParseSymtab() {
UUID dsc_uuid;
UUID process_shared_cache_uuid;
+ addr_t process_shared_cache_base_addr;
if (process) {
- process_shared_cache_uuid = GetProcessSharedCacheUUID(process);
+ GetProcessSharedCacheUUID(process, process_shared_cache_base_addr, process_shared_cache_uuid);
}
- // First see if we can find an exact match for the inferior process shared
- // cache UUID in
- // the development or non-development shared caches on disk.
+ // First see if we can find an exact match for the inferior process
+ // shared cache UUID in the development or non-development shared caches
+ // on disk.
if (process_shared_cache_uuid.IsValid()) {
if (dsc_development_filespec.Exists()) {
UUID dsc_development_uuid = GetSharedCacheUUID(
@@ -2716,8 +2684,7 @@ size_t ObjectFileMachO::ParseSymtab() {
if (process_shared_cache_uuid.IsValid() &&
dsc_uuid != process_shared_cache_uuid) {
// The on-disk dyld_shared_cache file is not the same as the one in
- // this
- // process' memory, don't use it.
+ // this process' memory, don't use it.
uuid_match = false;
ModuleSP module_sp(GetModule());
if (module_sp)
@@ -2745,11 +2712,9 @@ size_t ObjectFileMachO::ParseSymtab() {
offset = 0;
// The File addresses (from the in-memory Mach-O load commands) for
- // the shared libraries
- // in the shared library cache need to be adjusted by an offset to
- // match up with the
- // dylibOffset identifying field in the
- // dyld_cache_local_symbol_entry's. This offset is
+ // the shared libraries in the shared library cache need to be
+ // adjusted by an offset to match up with the dylibOffset identifying
+ // field in the dyld_cache_local_symbol_entry's. This offset is
// recorded in mapping_offset_value.
const uint64_t mapping_offset_value =
dsc_mapping_info_data.GetU64(&offset);
@@ -2843,8 +2808,8 @@ size_t ObjectFileMachO::ParseSymtab() {
if (symbol_name == NULL) {
// No symbol should be NULL, even the symbols with no
- // string values should have an offset zero which points
- // to an empty C-string
+ // string values should have an offset zero which
+ // points to an empty C-string
Host::SystemLog(
Host::eSystemLogError,
"error: DSC unmapped local symbol[%u] has invalid "
@@ -2879,14 +2844,13 @@ size_t ObjectFileMachO::ParseSymtab() {
// FIXME: In the .o files, we have a GSYM and a debug
// symbol for all the ObjC data. They
// have the same address, but we want to ensure that
- // we always find only the real symbol,
- // 'cause we don't currently correctly attribute the
+ // we always find only the real symbol, 'cause we
+ // don't currently correctly attribute the
// GSYM one to the ObjCClass/Ivar/MetaClass
- // symbol type. This is a temporary hack to make sure
- // the ObjectiveC symbols get treated
- // correctly. To do this right, we should coalesce
- // all the GSYM & global symbols that have the
- // same address.
+ // symbol type. This is a temporary hack to make
+ // sure the ObjectiveC symbols get treated correctly.
+ // To do this right, we should coalesce all the GSYM
+ // & global symbols that have the same address.
is_gsym = true;
sym[sym_idx].SetExternal(true);
@@ -2940,25 +2904,24 @@ size_t ObjectFileMachO::ParseSymtab() {
N_FUN_addr_to_sym_idx.insert(
std::make_pair(nlist.n_value, sym_idx));
// We use the current number of symbols in the
- // symbol table in lieu of
- // using nlist_idx in case we ever start trimming
- // entries out
+ // symbol table in lieu of using nlist_idx in case
+ // we ever start trimming entries out
N_FUN_indexes.push_back(sym_idx);
} else {
type = eSymbolTypeCompiler;
if (!N_FUN_indexes.empty()) {
- // Copy the size of the function into the original
+ // Copy the size of the function into the
+ // original
// STAB entry so we don't have
// to hunt for it later
symtab->SymbolAtIndex(N_FUN_indexes.back())
->SetByteSize(nlist.n_value);
N_FUN_indexes.pop_back();
// We don't really need the end function STAB as
- // it contains the size which
- // we already placed with the original symbol, so
- // don't add it if we want a
- // minimal symbol table
+ // it contains the size which we already placed
+ // with the original symbol, so don't add it if
+ // we want a minimal symbol table
add_nlist = false;
}
}
@@ -2985,19 +2948,17 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_BNSYM:
// We use the current number of symbols in the symbol
- // table in lieu of
- // using nlist_idx in case we ever start trimming
- // entries out
- // Skip these if we want minimal symbol tables
+ // table in lieu of using nlist_idx in case we ever
+ // start trimming entries out Skip these if we want
+ // minimal symbol tables
add_nlist = false;
break;
case N_ENSYM:
// Set the size of the N_BNSYM to the terminating
- // index of this N_ENSYM
- // so that we can always skip the entire symbol if we
- // need to navigate
- // more quickly at the source level when parsing STABS
+ // index of this N_ENSYM so that we can always skip
+ // the entire symbol if we need to navigate more
+ // quickly at the source level when parsing STABS
// Skip these if we want minimal symbol tables
add_nlist = false;
break;
@@ -3031,11 +2992,9 @@ size_t ObjectFileMachO::ParseSymtab() {
add_nlist = false;
if (N_SO_index != UINT32_MAX) {
// Set the size of the N_SO to the terminating
- // index of this N_SO
- // so that we can always skip the entire N_SO if
- // we need to navigate
- // more quickly at the source level when parsing
- // STABS
+ // index of this N_SO so that we can always skip
+ // the entire N_SO if we need to navigate more
+ // quickly at the source level when parsing STABS
symbol_ptr = symtab->SymbolAtIndex(N_SO_index);
symbol_ptr->SetByteSize(sym_idx);
symbol_ptr->SetSizeIsSibling(true);
@@ -3048,17 +3007,16 @@ size_t ObjectFileMachO::ParseSymtab() {
N_SO_index = UINT32_MAX;
} else {
// We use the current number of symbols in the
- // symbol table in lieu of
- // using nlist_idx in case we ever start trimming
- // entries out
+ // symbol table in lieu of using nlist_idx in case
+ // we ever start trimming entries out
const bool N_SO_has_full_path =
symbol_name[0] == '/';
if (N_SO_has_full_path) {
if ((N_SO_index == sym_idx - 1) &&
((sym_idx - 1) < num_syms)) {
// We have two consecutive N_SO entries where
- // the first contains a directory
- // and the second contains a full path.
+ // the first contains a directory and the
+ // second contains a full path.
sym[sym_idx - 1].GetMangled().SetValue(
ConstString(symbol_name), false);
m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
@@ -3072,9 +3030,9 @@ size_t ObjectFileMachO::ParseSymtab() {
} else if ((N_SO_index == sym_idx - 1) &&
((sym_idx - 1) < num_syms)) {
// This is usually the second N_SO entry that
- // contains just the filename,
- // so here we combine it with the first one if we
- // are minimizing the symbol table
+ // contains just the filename, so here we combine
+ // it with the first one if we are minimizing the
+ // symbol table
const char *so_path =
sym[sym_idx - 1]
.GetMangled()
@@ -3088,11 +3046,11 @@ size_t ObjectFileMachO::ParseSymtab() {
if (double_slash_pos != std::string::npos) {
// The linker has been generating bad N_SO
// entries with doubled up paths
- // in the format "%s%s" where the first string
- // in the DW_AT_comp_dir,
- // and the second is the directory for the
- // source file so you end up with
- // a path that looks like "/tmp/src//tmp/src/"
+ // in the format "%s%s" where the first
+ // string in the DW_AT_comp_dir, and the
+ // second is the directory for the source
+ // file so you end up with a path that looks
+ // like "/tmp/src//tmp/src/"
FileSpec so_dir(so_path, false);
if (!so_dir.Exists()) {
so_dir.SetFile(
@@ -3134,11 +3092,10 @@ size_t ObjectFileMachO::ParseSymtab() {
// INCL scopes
//----------------------------------------------------------------------
case N_BINCL:
- // include file beginning: name,,NO_SECT,0,sum
- // We use the current number of symbols in the symbol
- // table in lieu of
- // using nlist_idx in case we ever start trimming
- // entries out
+ // include file beginning: name,,NO_SECT,0,sum We use
+ // the current number of symbols in the symbol table
+ // in lieu of using nlist_idx in case we ever start
+ // trimming entries out
N_INCL_indexes.push_back(sym_idx);
type = eSymbolTypeScopeBegin;
break;
@@ -3146,10 +3103,9 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_EINCL:
// include file end: name,,NO_SECT,0,0
// Set the size of the N_BINCL to the terminating
- // index of this N_EINCL
- // so that we can always skip the entire symbol if we
- // need to navigate
- // more quickly at the source level when parsing STABS
+ // index of this N_EINCL so that we can always skip
+ // the entire symbol if we need to navigate more
+ // quickly at the source level when parsing STABS
if (!N_INCL_indexes.empty()) {
symbol_ptr =
symtab->SymbolAtIndex(N_INCL_indexes.back());
@@ -3199,11 +3155,10 @@ size_t ObjectFileMachO::ParseSymtab() {
// Left and Right Braces
//----------------------------------------------------------------------
case N_LBRAC:
- // left bracket: 0,,NO_SECT,nesting level,address
- // We use the current number of symbols in the symbol
- // table in lieu of
- // using nlist_idx in case we ever start trimming
- // entries out
+ // left bracket: 0,,NO_SECT,nesting level,address We
+ // use the current number of symbols in the symbol
+ // table in lieu of using nlist_idx in case we ever
+ // start trimming entries out
symbol_section = section_info.GetSection(
nlist.n_sect, nlist.n_value);
N_BRAC_indexes.push_back(sym_idx);
@@ -3213,10 +3168,9 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_RBRAC:
// right bracket: 0,,NO_SECT,nesting level,address
// Set the size of the N_LBRAC to the terminating
- // index of this N_RBRAC
- // so that we can always skip the entire symbol if we
- // need to navigate
- // more quickly at the source level when parsing STABS
+ // index of this N_RBRAC so that we can always skip
+ // the entire symbol if we need to navigate more
+ // quickly at the source level when parsing STABS
symbol_section = section_info.GetSection(
nlist.n_sect, nlist.n_value);
if (!N_BRAC_indexes.empty()) {
@@ -3240,9 +3194,8 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_BCOMM:
// begin common: name,,NO_SECT,0,0
// We use the current number of symbols in the symbol
- // table in lieu of
- // using nlist_idx in case we ever start trimming
- // entries out
+ // table in lieu of using nlist_idx in case we ever
+ // start trimming entries out
type = eSymbolTypeScopeBegin;
N_COMM_indexes.push_back(sym_idx);
break;
@@ -3256,10 +3209,10 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_ECOMM:
// end common: name,,n_sect,0,0
// Set the size of the N_BCOMM to the terminating
- // index of this N_ECOMM/N_ECOML
- // so that we can always skip the entire symbol if we
- // need to navigate
- // more quickly at the source level when parsing STABS
+ // index of this N_ECOMM/N_ECOML so that we can
+ // always skip the entire symbol if we need to
+ // navigate more quickly at the source level when
+ // parsing STABS
if (!N_COMM_indexes.empty()) {
symbol_ptr =
symtab->SymbolAtIndex(N_COMM_indexes.back());
@@ -3549,16 +3502,16 @@ size_t ObjectFileMachO::ParseSymtab() {
function_starts_count > 0) {
addr_t symbol_lookup_file_addr = nlist.n_value;
// Do an exact address match for non-ARM addresses,
- // else get the closest since
- // the symbol might be a thumb symbol which has an
- // address with bit zero set
+ // else get the closest since the symbol might be a
+ // thumb symbol which has an address with bit zero
+ // set
FunctionStarts::Entry *func_start_entry =
function_starts.FindEntry(
symbol_lookup_file_addr, !is_arm);
if (is_arm && func_start_entry) {
// Verify that the function start address is the
- // symbol address (ARM)
- // or the symbol address + 1 (thumb)
+ // symbol address (ARM) or the symbol address + 1
+ // (thumb)
if (func_start_entry->addr !=
symbol_lookup_file_addr &&
func_start_entry->addr !=
@@ -3590,8 +3543,8 @@ size_t ObjectFileMachO::ParseSymtab() {
addr_t next_symbol_file_addr =
next_func_start_entry->addr;
// Be sure the clear the Thumb address bit when
- // we calculate the size
- // from the current and next address
+ // we calculate the size from the current and
+ // next address
if (is_arm)
next_symbol_file_addr &=
THUMB_ADDRESS_BIT_MASK;
@@ -3610,12 +3563,10 @@ size_t ObjectFileMachO::ParseSymtab() {
if (is_debug == false) {
if (type == eSymbolTypeCode) {
// See if we can find a N_FUN entry for any code
- // symbols.
- // If we do find a match, and the name matches, then
- // we
- // can merge the two into just the function symbol
- // to avoid
- // duplicate entries in the symbol table
+ // symbols. If we do find a match, and the name
+ // matches, then we can merge the two into just the
+ // function symbol to avoid duplicate entries in
+ // the symbol table
std::pair<ValueToSymbolIndexMap::const_iterator,
ValueToSymbolIndexMap::const_iterator>
range;
@@ -3663,12 +3614,10 @@ size_t ObjectFileMachO::ParseSymtab() {
type == eSymbolTypeObjCMetaClass ||
type == eSymbolTypeObjCIVar) {
// See if we can find a N_STSYM entry for any data
- // symbols.
- // If we do find a match, and the name matches, then
- // we
- // can merge the two into just the Static symbol to
- // avoid
- // duplicate entries in the symbol table
+ // symbols. If we do find a match, and the name
+ // matches, then we can merge the two into just the
+ // Static symbol to avoid duplicate entries in the
+ // symbol table
std::pair<ValueToSymbolIndexMap::const_iterator,
ValueToSymbolIndexMap::const_iterator>
range;
@@ -3710,8 +3659,8 @@ size_t ObjectFileMachO::ParseSymtab() {
Mangled::ePreferMangled)
.GetCString();
if (gsym_name) {
- // Combine N_GSYM stab entries with the non stab
- // symbol
+ // Combine N_GSYM stab entries with the non
+ // stab symbol
ConstNameToSymbolIndexMap::const_iterator pos =
N_GSYM_name_to_sym_idx.find(gsym_name);
if (pos != N_GSYM_name_to_sym_idx.end()) {
@@ -3827,9 +3776,8 @@ size_t ObjectFileMachO::ParseSymtab() {
symbol_name = strtab_data.PeekCStr(nlist.n_strx);
if (symbol_name == NULL) {
- // No symbol should be NULL, even the symbols with no
- // string values should have an offset zero which points
- // to an empty C-string
+ // No symbol should be NULL, even the symbols with no string values
+ // should have an offset zero which points to an empty C-string
Host::SystemLog(Host::eSystemLogError,
"error: symbol[%u] has invalid string table offset "
"0x%x in %s, ignoring symbol\n",
@@ -3868,14 +3816,12 @@ size_t ObjectFileMachO::ParseSymtab() {
// FIXME: In the .o files, we have a GSYM and a debug symbol for all
// the ObjC data. They
// have the same address, but we want to ensure that we always find
- // only the real symbol,
- // 'cause we don't currently correctly attribute the GSYM one to the
- // ObjCClass/Ivar/MetaClass
- // symbol type. This is a temporary hack to make sure the
- // ObjectiveC symbols get treated
- // correctly. To do this right, we should coalesce all the GSYM &
- // global symbols that have the
- // same address.
+ // only the real symbol, 'cause we don't currently correctly
+ // attribute the GSYM one to the ObjCClass/Ivar/MetaClass symbol
+ // type. This is a temporary hack to make sure the ObjectiveC
+ // symbols get treated correctly. To do this right, we should
+ // coalesce all the GSYM & global symbols that have the same
+ // address.
is_gsym = true;
sym[sym_idx].SetExternal(true);
@@ -3922,24 +3868,21 @@ size_t ObjectFileMachO::ParseSymtab() {
N_FUN_addr_to_sym_idx.insert(
std::make_pair(nlist.n_value, sym_idx));
// We use the current number of symbols in the symbol table in
- // lieu of
- // using nlist_idx in case we ever start trimming entries out
+ // lieu of using nlist_idx in case we ever start trimming entries
+ // out
N_FUN_indexes.push_back(sym_idx);
} else {
type = eSymbolTypeCompiler;
if (!N_FUN_indexes.empty()) {
- // Copy the size of the function into the original STAB entry so
- // we don't have
- // to hunt for it later
+ // Copy the size of the function into the original STAB entry
+ // so we don't have to hunt for it later
symtab->SymbolAtIndex(N_FUN_indexes.back())
->SetByteSize(nlist.n_value);
N_FUN_indexes.pop_back();
- // We don't really need the end function STAB as it contains the
- // size which
- // we already placed with the original symbol, so don't add it
- // if we want a
- // minimal symbol table
+ // We don't really need the end function STAB as it contains
+ // the size which we already placed with the original symbol,
+ // so don't add it if we want a minimal symbol table
add_nlist = false;
}
}
@@ -3966,18 +3909,15 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_BNSYM:
// We use the current number of symbols in the symbol table in lieu
- // of
- // using nlist_idx in case we ever start trimming entries out
+ // of using nlist_idx in case we ever start trimming entries out
// Skip these if we want minimal symbol tables
add_nlist = false;
break;
case N_ENSYM:
// Set the size of the N_BNSYM to the terminating index of this
- // N_ENSYM
- // so that we can always skip the entire symbol if we need to
- // navigate
- // more quickly at the source level when parsing STABS
+ // N_ENSYM so that we can always skip the entire symbol if we need
+ // to navigate more quickly at the source level when parsing STABS
// Skip these if we want minimal symbol tables
add_nlist = false;
break;
@@ -4011,10 +3951,9 @@ size_t ObjectFileMachO::ParseSymtab() {
add_nlist = false;
if (N_SO_index != UINT32_MAX) {
// Set the size of the N_SO to the terminating index of this
- // N_SO
- // so that we can always skip the entire N_SO if we need to
- // navigate
- // more quickly at the source level when parsing STABS
+ // N_SO so that we can always skip the entire N_SO if we need
+ // to navigate more quickly at the source level when parsing
+ // STABS
symbol_ptr = symtab->SymbolAtIndex(N_SO_index);
symbol_ptr->SetByteSize(sym_idx);
symbol_ptr->SetSizeIsSibling(true);
@@ -4027,30 +3966,27 @@ size_t ObjectFileMachO::ParseSymtab() {
N_SO_index = UINT32_MAX;
} else {
// We use the current number of symbols in the symbol table in
- // lieu of
- // using nlist_idx in case we ever start trimming entries out
+ // lieu of using nlist_idx in case we ever start trimming entries
+ // out
const bool N_SO_has_full_path = symbol_name[0] == '/';
if (N_SO_has_full_path) {
if ((N_SO_index == sym_idx - 1) && ((sym_idx - 1) < num_syms)) {
// We have two consecutive N_SO entries where the first
- // contains a directory
- // and the second contains a full path.
+ // contains a directory and the second contains a full path.
sym[sym_idx - 1].GetMangled().SetValue(
ConstString(symbol_name), false);
m_nlist_idx_to_sym_idx[nlist_idx] = sym_idx - 1;
add_nlist = false;
} else {
- // This is the first entry in a N_SO that contains a directory
- // or
- // a full path to the source file
+ // This is the first entry in a N_SO that contains a
+ // directory or a full path to the source file
N_SO_index = sym_idx;
}
} else if ((N_SO_index == sym_idx - 1) &&
((sym_idx - 1) < num_syms)) {
// This is usually the second N_SO entry that contains just the
- // filename,
- // so here we combine it with the first one if we are minimizing
- // the symbol table
+ // filename, so here we combine it with the first one if we are
+ // minimizing the symbol table
const char *so_path =
sym[sym_idx - 1]
.GetMangled()
@@ -4061,16 +3997,14 @@ size_t ObjectFileMachO::ParseSymtab() {
const size_t double_slash_pos = full_so_path.find("//");
if (double_slash_pos != std::string::npos) {
// The linker has been generating bad N_SO entries with
- // doubled up paths
- // in the format "%s%s" where the first string in the
- // DW_AT_comp_dir,
- // and the second is the directory for the source file so
- // you end up with
- // a path that looks like "/tmp/src//tmp/src/"
+ // doubled up paths in the format "%s%s" where the first
+ // string in the DW_AT_comp_dir, and the second is the
+ // directory for the source file so you end up with a path
+ // that looks like "/tmp/src//tmp/src/"
FileSpec so_dir(so_path, false);
if (!so_dir.Exists()) {
- so_dir.SetFile(&full_so_path[double_slash_pos + 1],
- false);
+ so_dir.SetFile(&full_so_path[double_slash_pos + 1], false,
+ FileSpec::Style::native);
if (so_dir.Exists()) {
// Trim off the incorrect path
full_so_path.erase(0, double_slash_pos + 1);
@@ -4106,10 +4040,9 @@ size_t ObjectFileMachO::ParseSymtab() {
// INCL scopes
//----------------------------------------------------------------------
case N_BINCL:
- // include file beginning: name,,NO_SECT,0,sum
- // We use the current number of symbols in the symbol table in lieu
- // of
- // using nlist_idx in case we ever start trimming entries out
+ // include file beginning: name,,NO_SECT,0,sum We use the current
+ // number of symbols in the symbol table in lieu of using nlist_idx
+ // in case we ever start trimming entries out
N_INCL_indexes.push_back(sym_idx);
type = eSymbolTypeScopeBegin;
break;
@@ -4117,10 +4050,8 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_EINCL:
// include file end: name,,NO_SECT,0,0
// Set the size of the N_BINCL to the terminating index of this
- // N_EINCL
- // so that we can always skip the entire symbol if we need to
- // navigate
- // more quickly at the source level when parsing STABS
+ // N_EINCL so that we can always skip the entire symbol if we need
+ // to navigate more quickly at the source level when parsing STABS
if (!N_INCL_indexes.empty()) {
symbol_ptr = symtab->SymbolAtIndex(N_INCL_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
@@ -4169,10 +4100,9 @@ size_t ObjectFileMachO::ParseSymtab() {
// Left and Right Braces
//----------------------------------------------------------------------
case N_LBRAC:
- // left bracket: 0,,NO_SECT,nesting level,address
- // We use the current number of symbols in the symbol table in lieu
- // of
- // using nlist_idx in case we ever start trimming entries out
+ // left bracket: 0,,NO_SECT,nesting level,address We use the
+ // current number of symbols in the symbol table in lieu of using
+ // nlist_idx in case we ever start trimming entries out
symbol_section =
section_info.GetSection(nlist.n_sect, nlist.n_value);
N_BRAC_indexes.push_back(sym_idx);
@@ -4180,12 +4110,10 @@ size_t ObjectFileMachO::ParseSymtab() {
break;
case N_RBRAC:
- // right bracket: 0,,NO_SECT,nesting level,address
- // Set the size of the N_LBRAC to the terminating index of this
- // N_RBRAC
- // so that we can always skip the entire symbol if we need to
- // navigate
- // more quickly at the source level when parsing STABS
+ // right bracket: 0,,NO_SECT,nesting level,address Set the size of
+ // the N_LBRAC to the terminating index of this N_RBRAC so that we
+ // can always skip the entire symbol if we need to navigate more
+ // quickly at the source level when parsing STABS
symbol_section =
section_info.GetSection(nlist.n_sect, nlist.n_value);
if (!N_BRAC_indexes.empty()) {
@@ -4208,8 +4136,7 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_BCOMM:
// begin common: name,,NO_SECT,0,0
// We use the current number of symbols in the symbol table in lieu
- // of
- // using nlist_idx in case we ever start trimming entries out
+ // of using nlist_idx in case we ever start trimming entries out
type = eSymbolTypeScopeBegin;
N_COMM_indexes.push_back(sym_idx);
break;
@@ -4223,10 +4150,9 @@ size_t ObjectFileMachO::ParseSymtab() {
case N_ECOMM:
// end common: name,,n_sect,0,0
// Set the size of the N_BCOMM to the terminating index of this
- // N_ECOMM/N_ECOML
- // so that we can always skip the entire symbol if we need to
- // navigate
- // more quickly at the source level when parsing STABS
+ // N_ECOMM/N_ECOML so that we can always skip the entire symbol if
+ // we need to navigate more quickly at the source level when
+ // parsing STABS
if (!N_COMM_indexes.empty()) {
symbol_ptr = symtab->SymbolAtIndex(N_COMM_indexes.back());
symbol_ptr->SetByteSize(sym_idx + 1);
@@ -4486,15 +4412,13 @@ size_t ObjectFileMachO::ParseSymtab() {
if (symbol_byte_size == 0 && function_starts_count > 0) {
addr_t symbol_lookup_file_addr = nlist.n_value;
// Do an exact address match for non-ARM addresses, else get the
- // closest since
- // the symbol might be a thumb symbol which has an address with
- // bit zero set
+ // closest since the symbol might be a thumb symbol which has an
+ // address with bit zero set
FunctionStarts::Entry *func_start_entry =
function_starts.FindEntry(symbol_lookup_file_addr, !is_arm);
if (is_arm && func_start_entry) {
// Verify that the function start address is the symbol address
- // (ARM)
- // or the symbol address + 1 (thumb)
+ // (ARM) or the symbol address + 1 (thumb)
if (func_start_entry->addr != symbol_lookup_file_addr &&
func_start_entry->addr != (symbol_lookup_file_addr + 1)) {
// Not the right entry, NULL it out...
@@ -4515,8 +4439,7 @@ size_t ObjectFileMachO::ParseSymtab() {
if (next_func_start_entry) {
addr_t next_symbol_file_addr = next_func_start_entry->addr;
// Be sure the clear the Thumb address bit when we calculate
- // the size
- // from the current and next address
+ // the size from the current and next address
if (is_arm)
next_symbol_file_addr &= THUMB_ADDRESS_BIT_MASK;
symbol_byte_size = std::min<lldb::addr_t>(
@@ -4532,10 +4455,10 @@ size_t ObjectFileMachO::ParseSymtab() {
if (is_debug == false) {
if (type == eSymbolTypeCode) {
- // See if we can find a N_FUN entry for any code symbols.
- // If we do find a match, and the name matches, then we
- // can merge the two into just the function symbol to avoid
- // duplicate entries in the symbol table
+ // See if we can find a N_FUN entry for any code symbols. If we
+ // do find a match, and the name matches, then we can merge the
+ // two into just the function symbol to avoid duplicate entries
+ // in the symbol table
std::pair<ValueToSymbolIndexMap::const_iterator,
ValueToSymbolIndexMap::const_iterator>
range;
@@ -4552,9 +4475,8 @@ size_t ObjectFileMachO::ParseSymtab() {
Mangled::ePreferMangled)) {
m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
// We just need the flags from the linker symbol, so put
- // these flags
- // into the N_FUN flags to avoid duplicate symbols in the
- // symbol table
+ // these flags into the N_FUN flags to avoid duplicate
+ // symbols in the symbol table
sym[pos->second].SetExternal(sym[sym_idx].IsExternal());
sym[pos->second].SetFlags(nlist.n_type << 16 |
nlist.n_desc);
@@ -4577,10 +4499,10 @@ size_t ObjectFileMachO::ParseSymtab() {
type == eSymbolTypeObjCClass ||
type == eSymbolTypeObjCMetaClass ||
type == eSymbolTypeObjCIVar) {
- // See if we can find a N_STSYM entry for any data symbols.
- // If we do find a match, and the name matches, then we
- // can merge the two into just the Static symbol to avoid
- // duplicate entries in the symbol table
+ // See if we can find a N_STSYM entry for any data symbols. If we
+ // do find a match, and the name matches, then we can merge the
+ // two into just the Static symbol to avoid duplicate entries in
+ // the symbol table
std::pair<ValueToSymbolIndexMap::const_iterator,
ValueToSymbolIndexMap::const_iterator>
range;
@@ -4597,9 +4519,8 @@ size_t ObjectFileMachO::ParseSymtab() {
Mangled::ePreferMangled)) {
m_nlist_idx_to_sym_idx[nlist_idx] = pos->second;
// We just need the flags from the linker symbol, so put
- // these flags
- // into the N_STSYM flags to avoid duplicate symbols in the
- // symbol table
+ // these flags into the N_STSYM flags to avoid duplicate
+ // symbols in the symbol table
sym[pos->second].SetExternal(sym[sym_idx].IsExternal());
sym[pos->second].SetFlags(nlist.n_type << 16 |
nlist.n_desc);
@@ -4623,16 +4544,15 @@ size_t ObjectFileMachO::ParseSymtab() {
if (pos != N_GSYM_name_to_sym_idx.end()) {
const uint32_t GSYM_sym_idx = pos->second;
m_nlist_idx_to_sym_idx[nlist_idx] = GSYM_sym_idx;
- // Copy the address, because often the N_GSYM address has an
- // invalid address of zero
- // when the global is a common symbol
+ // Copy the address, because often the N_GSYM address has
+ // an invalid address of zero when the global is a common
+ // symbol
sym[GSYM_sym_idx].GetAddressRef().SetSection(
symbol_section);
sym[GSYM_sym_idx].GetAddressRef().SetOffset(symbol_value);
// We just need the flags from the linker symbol, so put
- // these flags
- // into the N_GSYM flags to avoid duplicate symbols in the
- // symbol table
+ // these flags into the N_GSYM flags to avoid duplicate
+ // symbols in the symbol table
sym[GSYM_sym_idx].SetFlags(nlist.n_type << 16 |
nlist.n_desc);
sym[sym_idx].Clear();
@@ -4739,8 +4659,8 @@ size_t ObjectFileMachO::ParseSymtab() {
}
}
- // Trim our symbols down to just what we ended up with after
- // removing any symbols.
+ // Trim our symbols down to just what we ended up with after removing any
+ // symbols.
if (sym_idx < num_syms) {
num_syms = sym_idx;
sym = symtab->Resize(num_syms);
@@ -4788,13 +4708,12 @@ size_t ObjectFileMachO::ParseSymtab() {
m_nlist_idx_to_sym_idx.find(stub_sym_id);
Symbol *stub_symbol = NULL;
if (index_pos != end_index_pos) {
- // We have a remapping from the original nlist index to
- // a current symbol index, so just look this up by index
+ // We have a remapping from the original nlist index to a
+ // current symbol index, so just look this up by index
stub_symbol = symtab->SymbolAtIndex(index_pos->second);
} else {
- // We need to lookup a symbol using the original nlist
- // symbol index since this index is coming from the
- // S_SYMBOL_STUBS
+ // We need to lookup a symbol using the original nlist symbol
+ // index since this index is coming from the S_SYMBOL_STUBS
stub_symbol = symtab->FindSymbolByID(stub_sym_id);
}
@@ -4803,12 +4722,9 @@ size_t ObjectFileMachO::ParseSymtab() {
if (stub_symbol->GetType() == eSymbolTypeUndefined) {
// Change the external symbol into a trampoline that makes
- // sense
- // These symbols were N_UNDF N_EXT, and are useless to us,
- // so we
- // can re-use them so we don't have to make up a synthetic
- // symbol
- // for no good reason.
+ // sense These symbols were N_UNDF N_EXT, and are useless
+ // to us, so we can re-use them so we don't have to make up
+ // a synthetic symbol for no good reason.
if (resolver_addresses.find(symbol_stub_addr) ==
resolver_addresses.end())
stub_symbol->SetType(eSymbolTypeTrampoline);
@@ -4853,8 +4769,8 @@ size_t ObjectFileMachO::ParseSymtab() {
if (!trie_entries.empty()) {
for (const auto &e : trie_entries) {
if (e.entry.import_name) {
- // Only add indirect symbols from the Trie entries if we
- // didn't have a N_INDR nlist entry for this already
+ // Only add indirect symbols from the Trie entries if we didn't have
+ // a N_INDR nlist entry for this already
if (indirect_symbol_names.find(e.entry.name) ==
indirect_symbol_names.end()) {
// Make a synthetic symbol to describe re-exported symbol.
@@ -4905,7 +4821,7 @@ void ObjectFileMachO::Dump(Stream *s) {
GetArchitecture(header_arch);
*s << ", file = '" << m_file
- << "', arch = " << header_arch.GetArchitectureName() << "\n";
+ << "', triple = " << header_arch.GetTriple().getTriple() << "\n";
SectionList *sections = GetSectionList();
if (sections)
@@ -4943,7 +4859,7 @@ bool ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header,
if (!memcmp(uuid_bytes, opencl_uuid, 16))
return false;
- uuid.SetBytes(uuid_bytes);
+ uuid = UUID::fromOptionalData(uuid_bytes, 16);
return true;
}
return false;
@@ -4953,6 +4869,21 @@ bool ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header,
return false;
}
+static const char *GetOSName(uint32_t cmd) {
+ switch (cmd) {
+ case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
+ return "ios";
+ case llvm::MachO::LC_VERSION_MIN_MACOSX:
+ return "macosx";
+ case llvm::MachO::LC_VERSION_MIN_TVOS:
+ return "tvos";
+ case llvm::MachO::LC_VERSION_MIN_WATCHOS:
+ return "watchos";
+ default:
+ llvm_unreachable("unexpected LC_VERSION load command");
+ }
+}
+
bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
const lldb_private::DataExtractor &data,
lldb::offset_t lc_offset,
@@ -4968,16 +4899,16 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
if (header.filetype == MH_PRELOAD) {
if (header.cputype == CPU_TYPE_ARM) {
- // If this is a 32-bit arm binary, and it's a standalone binary,
- // force the Vendor to Apple so we don't accidentally pick up
- // the generic armv7 ABI at runtime. Apple's armv7 ABI always uses
- // r7 for the frame pointer register; most other armv7 ABIs use a
- // combination of r7 and r11.
+ // If this is a 32-bit arm binary, and it's a standalone binary, force
+ // the Vendor to Apple so we don't accidentally pick up the generic
+ // armv7 ABI at runtime. Apple's armv7 ABI always uses r7 for the
+ // frame pointer register; most other armv7 ABIs use a combination of
+ // r7 and r11.
triple.setVendor(llvm::Triple::Apple);
} else {
// Set vendor to an unspecified unknown or a "*" so it can match any
- // vendor
- // This is required for correct behavior of EFI debugging on x86_64
+ // vendor This is required for correct behavior of EFI debugging on
+ // x86_64
triple.setVendor(llvm::Triple::UnknownVendor);
triple.setVendorName(llvm::StringRef());
}
@@ -4991,23 +4922,29 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
if (data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
+ uint32_t major, minor, patch;
+ struct version_min_command version_min;
+
+ llvm::SmallString<16> os_name;
+ llvm::raw_svector_ostream os(os_name);
+
switch (load_cmd.cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
- triple.setOS(llvm::Triple::IOS);
- return true;
-
case llvm::MachO::LC_VERSION_MIN_MACOSX:
- triple.setOS(llvm::Triple::MacOSX);
- return true;
-
case llvm::MachO::LC_VERSION_MIN_TVOS:
- triple.setOS(llvm::Triple::TvOS);
- return true;
-
case llvm::MachO::LC_VERSION_MIN_WATCHOS:
- triple.setOS(llvm::Triple::WatchOS);
+ if (load_cmd.cmdsize != sizeof(version_min))
+ break;
+ data.ExtractBytes(cmd_offset,
+ sizeof(version_min), data.GetByteOrder(),
+ &version_min);
+ major = version_min.version >> 16;
+ minor = (version_min.version >> 8) & 0xffu;
+ patch = version_min.version & 0xffu;
+ os << GetOSName(load_cmd.cmd) << major << '.' << minor << '.'
+ << patch;
+ triple.setOSName(os.str());
return true;
-
default:
break;
}
@@ -5048,7 +4985,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
std::vector<std::string> rpath_relative_paths;
std::vector<std::string> at_exec_relative_paths;
const bool resolve_path = false; // Don't resolve the dependent file paths
- // since they may not reside on this system
+ // since they may not reside on this
+ // system
uint32_t i;
for (i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
@@ -5112,12 +5050,9 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
for (const auto &rpath : rpath_paths) {
std::string path = rpath;
path += rpath_relative_path;
- // It is OK to resolve this path because we must find a file on
- // disk for us to accept it anyway if it is rpath relative.
+ // It is OK to resolve this path because we must find a file on disk
+ // for us to accept it anyway if it is rpath relative.
FileSpec file_spec(path, true);
- // Remove any redundant parts of the path (like "../foo") since
- // LC_RPATH values often contain "..".
- file_spec = file_spec.GetNormalizedPath();
if (file_spec.Exists() && files.AppendIfUnique(file_spec)) {
count++;
break;
@@ -5135,11 +5070,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
for (const auto &at_exec_relative_path : at_exec_relative_paths) {
FileSpec file_spec =
exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
- file_spec = file_spec.GetNormalizedPath();
- if (file_spec.Exists() && files.AppendIfUnique(file_spec)) {
+ if (file_spec.Exists() && files.AppendIfUnique(file_spec))
count++;
- break;
- }
}
}
}
@@ -5148,17 +5080,15 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
// If the object file is not an executable it can't hold the entry point.
- // m_entry_point_address
- // is initialized to an invalid address, so we can just return that.
- // If m_entry_point_address is valid it means we've found it already, so
- // return the cached value.
+ // m_entry_point_address is initialized to an invalid address, so we can just
+ // return that. If m_entry_point_address is valid it means we've found it
+ // already, so return the cached value.
if (!IsExecutable() || m_entry_point_address.IsValid())
return m_entry_point_address;
// Otherwise, look for the UnixThread or Thread command. The data for the
- // Thread command is given in
- // /usr/include/mach-o.h, but it is basically:
+ // Thread command is given in /usr/include/mach-o.h, but it is basically:
//
// uint32_t flavor - this is the flavor argument you would pass to
// thread_get_state
@@ -5172,9 +5102,9 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
// FIXME: We will need to have a "RegisterContext data provider" class at some
// point that can get all the registers
// out of data in this form & attach them to a given thread. That should
- // underlie the MacOS X User process plugin,
- // and we'll also need it for the MacOS X Core File process plugin. When we
- // have that we can also use it here.
+ // underlie the MacOS X User process plugin, and we'll also need it for the
+ // MacOS X Core File process plugin. When we have that we can also use it
+ // here.
//
// For now we hard-code the offsets and flavors we need:
//
@@ -5279,16 +5209,14 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
if (start_address != LLDB_INVALID_ADDRESS) {
// We got the start address from the load commands, so now resolve that
- // address in the sections
- // of this ObjectFile:
+ // address in the sections of this ObjectFile:
if (!m_entry_point_address.ResolveAddressUsingFileSections(
start_address, GetSectionList())) {
m_entry_point_address.Clear();
}
} else {
// We couldn't read the UnixThread load command - maybe it wasn't there.
- // As a fallback look for the
- // "start" symbol in the main executable.
+ // As a fallback look for the "start" symbol in the main executable.
ModuleSP module_sp(GetModule());
@@ -5353,8 +5281,8 @@ std::string ObjectFileMachO::GetIdentifierString() {
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- // First, look over the load commands for an LC_NOTE load command
- // with data_owner string "kern ver str" & use that if found.
+ // First, look over the load commands for an LC_NOTE load command with
+ // data_owner string "kern ver str" & use that if found.
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
@@ -5370,8 +5298,8 @@ std::string ObjectFileMachO::GetIdentifierString() {
uint64_t fileoff = m_data.GetU64_unchecked (&offset);
uint64_t size = m_data.GetU64_unchecked (&offset);
- // "kern ver str" has a uint32_t version and then a
- // nul terminated c-string.
+ // "kern ver str" has a uint32_t version and then a nul terminated
+ // c-string.
if (strcmp ("kern ver str", data_owner) == 0)
{
offset = fileoff;
@@ -5398,8 +5326,8 @@ std::string ObjectFileMachO::GetIdentifierString() {
offset = cmd_offset + lc.cmdsize;
}
- // Second, make a pass over the load commands looking for an
- // obsolete LC_IDENT load command.
+ // Second, make a pass over the load commands looking for an obsolete
+ // LC_IDENT load command.
offset = MachHeaderSizeFromMagic(m_header.magic);
for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
@@ -5444,7 +5372,8 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo (addr_t &address, UUID &uuid) {
uint64_t fileoff = m_data.GetU64_unchecked (&offset);
uint64_t size = m_data.GetU64_unchecked (&offset);
- // "main bin spec" (main binary specification) data payload is formatted:
+ // "main bin spec" (main binary specification) data payload is
+ // formatted:
// uint32_t version [currently 1]
// uint32_t type [0 == unspecified, 1 == kernel, 2 == user process]
// uint64_t address [ UINT64_MAX if address not specified ]
@@ -5461,12 +5390,11 @@ bool ObjectFileMachO::GetCorefileMainBinaryInfo (addr_t &address, UUID &uuid) {
uuid_t raw_uuid;
memset (raw_uuid, 0, sizeof (uuid_t));
- if (m_data.GetU32 (&offset, &type, 1)
- && m_data.GetU64 (&offset, &address, 1)
- && m_data.CopyData (offset, sizeof (uuid_t), raw_uuid) != 0
- && uuid.SetBytes (raw_uuid, sizeof (uuid_t)))
- {
- return true;
+ if (m_data.GetU32(&offset, &type, 1) &&
+ m_data.GetU64(&offset, &address, 1) &&
+ m_data.CopyData(offset, sizeof(uuid_t), raw_uuid) != 0) {
+ uuid = UUID::fromOptionalData(raw_uuid, sizeof(uuid_t));
+ return true;
}
}
}
@@ -5525,9 +5453,9 @@ ObjectFile::Type ObjectFileMachO::CalculateType() {
// UUID load command.
UUID uuid;
if (GetUUID(&uuid)) {
- // this checking for the UUID load command is not enough
- // we could eventually look for the symbol named
- // "OSKextGetCurrentIdentifier" as this is required of kexts
+ // this checking for the UUID load command is not enough we could
+ // eventually look for the symbol named "OSKextGetCurrentIdentifier" as
+ // this is required of kexts
if (m_strata == eStrataInvalid)
m_strata = eStrataKernel;
return eTypeSharedLibrary;
@@ -5569,9 +5497,9 @@ ObjectFile::Strata ObjectFileMachO::CalculateStrata() {
// UUID load command.
UUID uuid;
if (GetUUID(&uuid)) {
- // this checking for the UUID load command is not enough
- // we could eventually look for the symbol named
- // "OSKextGetCurrentIdentifier" as this is required of kexts
+ // this checking for the UUID load command is not enough we could
+ // eventually look for the symbol named "OSKextGetCurrentIdentifier" as
+ // this is required of kexts
if (m_type == eTypeInvalid)
m_type = eTypeSharedLibrary;
@@ -5618,8 +5546,7 @@ ObjectFile::Strata ObjectFileMachO::CalculateStrata() {
return eStrataUnknown;
}
-uint32_t ObjectFileMachO::GetVersion(uint32_t *versions,
- uint32_t num_versions) {
+llvm::VersionTuple ObjectFileMachO::GetVersion() {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
@@ -5647,23 +5574,13 @@ uint32_t ObjectFileMachO::GetVersion(uint32_t *versions,
}
if (version_cmd == LC_ID_DYLIB) {
- if (versions != NULL && num_versions > 0) {
- if (num_versions > 0)
- versions[0] = (version & 0xFFFF0000ull) >> 16;
- if (num_versions > 1)
- versions[1] = (version & 0x0000FF00ull) >> 8;
- if (num_versions > 2)
- versions[2] = (version & 0x000000FFull);
- // Fill in an remaining version numbers with invalid values
- for (i = 3; i < num_versions; ++i)
- versions[i] = UINT32_MAX;
- }
- // The LC_ID_DYLIB load command has a version with 3 version numbers
- // in it, so always return 3
- return 3;
+ unsigned major = (version & 0xFFFF0000ull) >> 16;
+ unsigned minor = (version & 0x0000FF00ull) >> 8;
+ unsigned subminor = (version & 0x000000FFull);
+ return llvm::VersionTuple(major, minor, subminor);
}
}
- return false;
+ return llvm::VersionTuple();
}
bool ObjectFileMachO::GetArchitecture(ArchSpec &arch) {
@@ -5676,21 +5593,40 @@ bool ObjectFileMachO::GetArchitecture(ArchSpec &arch) {
return false;
}
-UUID ObjectFileMachO::GetProcessSharedCacheUUID(Process *process) {
- UUID uuid;
+void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process, addr_t &base_addr, UUID &uuid) {
+ uuid.Clear();
+ base_addr = LLDB_INVALID_ADDRESS;
if (process && process->GetDynamicLoader()) {
DynamicLoader *dl = process->GetDynamicLoader();
- addr_t load_address;
LazyBool using_shared_cache;
LazyBool private_shared_cache;
- dl->GetSharedCacheInformation(load_address, uuid, using_shared_cache,
+ dl->GetSharedCacheInformation(base_addr, uuid, using_shared_cache,
private_shared_cache);
}
- return uuid;
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("inferior process shared cache has a UUID of %s, base address 0x%" PRIx64 , uuid.GetAsString().c_str(), base_addr);
}
-UUID ObjectFileMachO::GetLLDBSharedCacheUUID() {
- UUID uuid;
+// From dyld SPI header dyld_process_info.h
+typedef void *dyld_process_info;
+struct lldb_copy__dyld_process_cache_info {
+ uuid_t cacheUUID; // UUID of cache used by process
+ uint64_t cacheBaseAddress; // load address of dyld shared cache
+ bool noCache; // process is running without a dyld cache
+ bool privateCache; // process is using a private copy of its dyld cache
+};
+
+// #including mach/mach.h pulls in machine.h & CPU_TYPE_ARM etc conflicts with llvm
+// enum definitions llvm::MachO::CPU_TYPE_ARM turning them into compile errors.
+// So we need to use the actual underlying types of task_t and kern_return_t
+// below.
+extern "C" unsigned int /*task_t*/ mach_task_self();
+
+void ObjectFileMachO::GetLLDBSharedCacheUUID(addr_t &base_addr, UUID &uuid) {
+ uuid.Clear();
+ base_addr = LLDB_INVALID_ADDRESS;
+
#if defined(__APPLE__) && \
(defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
uint8_t *(*dyld_get_all_image_infos)(void);
@@ -5708,25 +5644,60 @@ UUID ObjectFileMachO::GetLLDBSharedCacheUUID() {
sharedCacheUUID_address =
(uuid_t *)((uint8_t *)dyld_all_image_infos_address +
160); // sharedCacheUUID <mach-o/dyld_images.h>
+ if (*version >= 15)
+ base_addr = *(uint64_t *) ((uint8_t *) dyld_all_image_infos_address
+ + 176); // sharedCacheBaseAddress <mach-o/dyld_images.h>
} else {
sharedCacheUUID_address =
(uuid_t *)((uint8_t *)dyld_all_image_infos_address +
84); // sharedCacheUUID <mach-o/dyld_images.h>
+ if (*version >= 15) {
+ base_addr = 0;
+ base_addr = *(uint32_t *) ((uint8_t *) dyld_all_image_infos_address
+ + 100); // sharedCacheBaseAddress <mach-o/dyld_images.h>
+ }
+ }
+ uuid = UUID::fromOptionalData(sharedCacheUUID_address, sizeof(uuid_t));
+ }
+ }
+ } else {
+ // Exists in macOS 10.12 and later, iOS 10.0 and later - dyld SPI
+ dyld_process_info (*dyld_process_info_create)(unsigned int /* task_t */ task, uint64_t timestamp, unsigned int /*kern_return_t*/ *kernelError);
+ void (*dyld_process_info_get_cache)(void *info, void *cacheInfo);
+ void (*dyld_process_info_release)(dyld_process_info info);
+
+ dyld_process_info_create = (void *(*)(unsigned int /* task_t */, uint64_t, unsigned int /*kern_return_t*/ *))
+ dlsym (RTLD_DEFAULT, "_dyld_process_info_create");
+ dyld_process_info_get_cache = (void (*)(void *, void *))
+ dlsym (RTLD_DEFAULT, "_dyld_process_info_get_cache");
+ dyld_process_info_release = (void (*)(void *))
+ dlsym (RTLD_DEFAULT, "_dyld_process_info_release");
+
+ if (dyld_process_info_create && dyld_process_info_get_cache) {
+ unsigned int /*kern_return_t */ kern_ret;
+ dyld_process_info process_info = dyld_process_info_create(::mach_task_self(), 0, &kern_ret);
+ if (process_info) {
+ struct lldb_copy__dyld_process_cache_info sc_info;
+ memset (&sc_info, 0, sizeof (struct lldb_copy__dyld_process_cache_info));
+ dyld_process_info_get_cache (process_info, &sc_info);
+ if (sc_info.cacheBaseAddress != 0) {
+ base_addr = sc_info.cacheBaseAddress;
+ uuid = UUID::fromOptionalData(sc_info.cacheUUID, sizeof(uuid_t));
}
- uuid.SetBytes(sharedCacheUUID_address);
+ dyld_process_info_release (process_info);
}
}
}
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS));
+ if (log && uuid.IsValid())
+ log->Printf("lldb's in-memory shared cache has a UUID of %s base address of 0x%" PRIx64, uuid.GetAsString().c_str(), base_addr);
#endif
- return uuid;
}
-uint32_t ObjectFileMachO::GetMinimumOSVersion(uint32_t *versions,
- uint32_t num_versions) {
- if (m_min_os_versions.empty()) {
+llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() {
+ if (!m_min_os_version) {
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
- bool success = false;
- for (uint32_t i = 0; success == false && i < m_header.ncmds; ++i) {
+ for (uint32_t i = 0; i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
version_min_command lc;
@@ -5742,35 +5713,21 @@ uint32_t ObjectFileMachO::GetMinimumOSVersion(uint32_t *versions,
const uint32_t yy = (lc.version >> 8) & 0xffu;
const uint32_t zz = lc.version & 0xffu;
if (xxxx) {
- m_min_os_versions.push_back(xxxx);
- m_min_os_versions.push_back(yy);
- m_min_os_versions.push_back(zz);
+ m_min_os_version = llvm::VersionTuple(xxxx, yy, zz);
+ break;
}
- success = true;
}
}
offset = load_cmd_offset + lc.cmdsize;
}
- if (success == false) {
- // Push an invalid value so we don't keep trying to
- m_min_os_versions.push_back(UINT32_MAX);
+ if (!m_min_os_version) {
+ // Set version to an empty value so we don't keep trying to
+ m_min_os_version = llvm::VersionTuple();
}
}
- if (m_min_os_versions.size() > 1 || m_min_os_versions[0] != UINT32_MAX) {
- if (versions != NULL && num_versions > 0) {
- for (size_t i = 0; i < num_versions; ++i) {
- if (i < m_min_os_versions.size())
- versions[i] = m_min_os_versions[i];
- else
- versions[i] = 0;
- }
- }
- return m_min_os_versions.size();
- }
- // Call the superclasses version that will empty out the data
- return ObjectFile::GetMinimumOSVersion(versions, num_versions);
+ return *m_min_os_version;
}
uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
@@ -5797,20 +5754,29 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
m_sdk_versions.push_back(xxxx);
m_sdk_versions.push_back(yy);
m_sdk_versions.push_back(zz);
+ success = true;
+ } else {
+ GetModule()->ReportWarning(
+ "minimum OS version load command with invalid (0) version found.");
}
- success = true;
}
}
offset = load_cmd_offset + lc.cmdsize;
}
if (success == false) {
- // Push an invalid value so we don't keep trying to
+ // Push an invalid value so we don't try to find
+ // the version # again on the next call to this
+ // method.
m_sdk_versions.push_back(UINT32_MAX);
}
}
- if (m_sdk_versions.size() > 1 || m_sdk_versions[0] != UINT32_MAX) {
+ // Legitimate version numbers will have 3 entries pushed
+ // on to m_sdk_versions. If we only have one value, it's
+ // the sentinel value indicating that this object file
+ // does not have a valid minimum os version #.
+ if (m_sdk_versions.size() > 1) {
if (versions != NULL && num_versions > 0) {
for (size_t i = 0; i < num_versions; ++i) {
if (i < m_sdk_versions.size())
@@ -5843,9 +5809,9 @@ lldb_private::ConstString ObjectFileMachO::GetPluginName() {
uint32_t ObjectFileMachO::GetPluginVersion() { return 1; }
Section *ObjectFileMachO::GetMachHeaderSection() {
- // Find the first address of the mach header which is the first non-zero
- // file sized section whose file offset is zero. This is the base file address
- // of the mach-o file which can be subtracted from the vmaddr of the other
+ // Find the first address of the mach header which is the first non-zero file
+ // sized section whose file offset is zero. This is the base file address of
+ // the mach-o file which can be subtracted from the vmaddr of the other
// segments found in memory and added to the load address
ModuleSP module_sp = GetModule();
if (module_sp) {
@@ -5883,8 +5849,8 @@ lldb::addr_t ObjectFileMachO::CalculateSectionLoadAddressForMemoryImage(
module_sp.get() == section->GetModule().get()) {
// Ignore __LINKEDIT and __DWARF segments
if (section->GetName() == GetSegmentNameLINKEDIT()) {
- // Only map __LINKEDIT if we have an in memory image and this isn't
- // a kernel binary like a kext or mach_kernel.
+ // Only map __LINKEDIT if we have an in memory image and this isn't a
+ // kernel binary like a kext or mach_kernel.
const bool is_memory_image = (bool)m_process_wp.lock();
const Strata strata = GetStrata();
if (is_memory_image == false || strata == eStrataKernel)
@@ -5910,9 +5876,8 @@ bool ObjectFileMachO::SetLoadAddress(Target &target, lldb::addr_t value,
if (value_is_offset) {
// "value" is an offset to apply to each top level segment
for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find all
- // of the sections that size on disk (to avoid __PAGEZERO)
- // and load them
+ // Iterate through the object file sections to find all of the
+ // sections that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && section_sp->GetFileSize() > 0 &&
section_sp->IsThreadSpecific() == false &&
@@ -5920,8 +5885,7 @@ bool ObjectFileMachO::SetLoadAddress(Target &target, lldb::addr_t value,
// Ignore __LINKEDIT and __DWARF segments
if (section_sp->GetName() == GetSegmentNameLINKEDIT()) {
// Only map __LINKEDIT if we have an in memory image and this
- // isn't
- // a kernel binary like a kext or mach_kernel.
+ // isn't a kernel binary like a kext or mach_kernel.
const bool is_memory_image = (bool)m_process_wp.lock();
const Strata strata = GetStrata();
if (is_memory_image == false || strata == eStrataKernel)
@@ -6071,10 +6035,10 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
ThreadList &thread_list = process_sp->GetThreadList();
const uint32_t num_threads = thread_list.GetSize();
- // Make an array of LC_THREAD data items. Each one contains
- // the contents of the LC_THREAD load command. The data doesn't
- // contain the load command + load command size, we will
- // add the load command and load command size as we emit the data.
+ // Make an array of LC_THREAD data items. Each one contains the
+ // contents of the LC_THREAD load command. The data doesn't contain
+ // the load command + load command size, we will add the load command
+ // and load command size as we emit the data.
std::vector<StreamString> LC_THREAD_datas(num_threads);
for (auto &LC_THREAD_data : LC_THREAD_datas) {
LC_THREAD_data.GetFlags().Set(Stream::eBinary);
@@ -6234,8 +6198,8 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
bytes_left -= bytes_read;
addr += bytes_read;
} else {
- // Some pages within regions are not readable, those
- // should be zero filled
+ // Some pages within regions are not readable, those should
+ // be zero filled
memset(bytes, 0, bytes_to_read);
size_t bytes_written = bytes_to_read;
error = core_file.Write(bytes, bytes_written);
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index 9a42f41a4c94..be64518064b5 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -86,7 +86,7 @@ public:
uint32_t GetAddressByteSize() const override;
- lldb::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
+ lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;
lldb_private::Symtab *GetSymtab() override;
@@ -123,10 +123,9 @@ public:
ObjectFile::Strata CalculateStrata() override;
- uint32_t GetVersion(uint32_t *versions, uint32_t num_versions) override;
+ llvm::VersionTuple GetVersion() override;
- uint32_t GetMinimumOSVersion(uint32_t *versions,
- uint32_t num_versions) override;
+ llvm::VersionTuple GetMinimumOSVersion() override;
uint32_t GetSDKVersion(uint32_t *versions, uint32_t num_versions) override;
@@ -162,14 +161,14 @@ protected:
// with an on-disk dyld_shared_cache file. The process will record
// the shared cache UUID so the on-disk cache can be matched or rejected
// correctly.
- lldb_private::UUID GetProcessSharedCacheUUID(lldb_private::Process *);
+ void GetProcessSharedCacheUUID(lldb_private::Process *, lldb::addr_t &base_addr, lldb_private::UUID &uuid);
// Intended for same-host arm device debugging where lldb will read
// shared cache libraries out of its own memory instead of the remote
// process' memory as an optimization. If lldb's shared cache UUID
// does not match the process' shared cache UUID, this optimization
// should not be used.
- lldb_private::UUID GetLLDBSharedCacheUUID();
+ void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid);
lldb_private::Section *GetMachHeaderSection();
@@ -185,6 +184,18 @@ protected:
size_t ParseSymtab();
+ typedef lldb_private::RangeArray<uint32_t, uint32_t, 8> EncryptedFileRanges;
+ EncryptedFileRanges GetEncryptedFileRanges();
+
+ struct SegmentParsingContext;
+ void ProcessDysymtabCommand(const llvm::MachO::load_command &load_cmd,
+ lldb::offset_t offset);
+ void ProcessSegmentCommand(const llvm::MachO::load_command &load_cmd,
+ lldb::offset_t offset, uint32_t cmd_idx,
+ SegmentParsingContext &context);
+ void SanitizeSegmentCommand(llvm::MachO::segment_command_64 &seg_cmd,
+ uint32_t cmd_idx);
+
llvm::MachO::mach_header m_header;
static const lldb_private::ConstString &GetSegmentNameTEXT();
static const lldb_private::ConstString &GetSegmentNameDATA();
@@ -197,7 +208,7 @@ protected:
llvm::MachO::dysymtab_command m_dysymtab;
std::vector<llvm::MachO::segment_command_64> m_mach_segments;
std::vector<llvm::MachO::section_64> m_mach_sections;
- std::vector<uint32_t> m_min_os_versions;
+ llvm::Optional<llvm::VersionTuple> m_min_os_version;
std::vector<uint32_t> m_sdk_versions;
typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray;
lldb_private::Address m_entry_point_address;
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 77bfa7fe0a64..b2967f1532ab 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -236,8 +236,8 @@ bool ObjectFilePECOFF::SetLoadAddress(Target &target, addr_t value,
size_t sect_idx = 0;
for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find all
- // of the sections that have SHF_ALLOC in their flag bits.
+ // Iterate through the object file sections to find all of the sections
+ // that have SHF_ALLOC in their flag bits.
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && !section_sp->IsThreadSpecific()) {
if (target.GetSectionLoadList().SetSectionLoadAddress(
@@ -268,8 +268,8 @@ uint32_t ObjectFilePECOFF::GetAddressByteSize() const {
//----------------------------------------------------------------------
// NeedsEndianSwap
//
-// Return true if an endian swap needs to occur when extracting data
-// from this file.
+// Return true if an endian swap needs to occur when extracting data from this
+// file.
//----------------------------------------------------------------------
bool ObjectFilePECOFF::NeedsEndianSwap() const {
#if defined(__LITTLE_ENDIAN__)
@@ -552,8 +552,8 @@ Symtab *ObjectFilePECOFF::GetSymtab() {
// are followed by a 4-byte string table offset. Else these
// 8 bytes contain the symbol name
if (symtab_data.GetU32(&offset) == 0) {
- // Long string that doesn't fit into the symbol table name,
- // so now we must read the 4 byte string table offset
+ // Long string that doesn't fit into the symbol table name, so
+ // now we must read the 4 byte string table offset
uint32_t strtab_offset = symtab_data.GetU32(&offset);
symbol_name_cstr = strtab_data.PeekCStr(strtab_offset);
symbol_name.assign(symbol_name_cstr);
@@ -692,10 +692,12 @@ void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
static ConstString g_sect_name_dwarf_debug_line(".debug_line");
static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
+ static ConstString g_sect_name_dwarf_debug_names(".debug_names");
static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
static ConstString g_sect_name_dwarf_debug_str(".debug_str");
+ static ConstString g_sect_name_dwarf_debug_types(".debug_types");
static ConstString g_sect_name_eh_frame(".eh_frame");
static ConstString g_sect_name_go_symtab(".gosymtab");
SectionType section_type = eSectionTypeOther;
@@ -736,6 +738,8 @@ void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
section_type = eSectionTypeDWARFDebugLoc;
else if (const_sect_name == g_sect_name_dwarf_debug_macinfo)
section_type = eSectionTypeDWARFDebugMacInfo;
+ else if (const_sect_name == g_sect_name_dwarf_debug_names)
+ section_type = eSectionTypeDWARFDebugNames;
else if (const_sect_name == g_sect_name_dwarf_debug_pubnames)
section_type = eSectionTypeDWARFDebugPubNames;
else if (const_sect_name == g_sect_name_dwarf_debug_pubtypes)
@@ -744,6 +748,8 @@ void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
section_type = eSectionTypeDWARFDebugRanges;
else if (const_sect_name == g_sect_name_dwarf_debug_str)
section_type = eSectionTypeDWARFDebugStr;
+ else if (const_sect_name == g_sect_name_dwarf_debug_types)
+ section_type = eSectionTypeDWARFDebugTypes;
else if (const_sect_name == g_sect_name_eh_frame)
section_type = eSectionTypeEHFrame;
else if (const_sect_name == g_sect_name_go_symtab)
diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
index 75bc518f7538..3f6083931513 100644
--- a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
+++ b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
@@ -312,8 +312,8 @@ bool OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list,
}
std::vector<Goroutine> goroutines;
// The threads that are in "new_thread_list" upon entry are the threads from
- // the
- // lldb_private::Process subclass, no memory threads will be in this list.
+ // the lldb_private::Process subclass, no memory threads will be in this
+ // list.
Status err;
for (uint64_t i = 0; i < allglen; ++i) {
@@ -402,7 +402,6 @@ lldb::ThreadSP OperatingSystemGo::CreateThread(lldb::tid_t tid,
ValueObjectSP OperatingSystemGo::FindGlobal(TargetSP target, const char *name) {
VariableList variable_list;
- const bool append = true;
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
@@ -414,7 +413,7 @@ ValueObjectSP OperatingSystemGo::FindGlobal(TargetSP target, const char *name) {
}
uint32_t match_count = target->GetImages().FindGlobalVariables(
- ConstString(name), append, 1, variable_list);
+ ConstString(name), 1, variable_list);
if (match_count > 0) {
ExecutionContextScope *exe_scope = target->GetProcessSP().get();
if (exe_scope == NULL)
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index b71f3cf04c33..d6252c473270 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -50,8 +50,8 @@ void OperatingSystemPython::Terminate() {
OperatingSystem *OperatingSystemPython::CreateInstance(Process *process,
bool force) {
- // Python OperatingSystem plug-ins must be requested by name, so force must be
- // true
+ // Python OperatingSystem plug-ins must be requested by name, so force must
+ // be true
FileSpec python_os_plugin_spec(process->GetPythonOSPluginPath());
if (python_os_plugin_spec && python_os_plugin_spec.Exists()) {
std::unique_ptr<OperatingSystemPython> os_ap(
@@ -156,9 +156,10 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
- // First thing we have to do is to try to get the API lock, and the run lock.
- // We're going to change the thread content of the process, and we're going
- // to use python, which requires the API lock to do it.
+ // First thing we have to do is to try to get the API lock, and the
+ // interpreter lock. We're going to change the thread content of the process,
+ // and we're going to use python, which requires the API lock to do it. We
+ // need the interpreter lock to make sure thread_info_dict stays alive.
//
// If someone already has the API lock, that is ok, we just want to avoid
// external code from making new API calls while this call is happening.
@@ -166,9 +167,10 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
// This is a recursive lock so we can grant it to any Python code called on
// the stack below us.
Target &target = m_process->GetTarget();
- std::unique_lock<std::recursive_mutex> lock(target.GetAPIMutex(),
- std::defer_lock);
- lock.try_lock();
+ std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
+ std::defer_lock);
+ api_lock.try_lock();
+ auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
if (log)
log->Printf("OperatingSystemPython::UpdateThreadList() fetching thread "
@@ -176,20 +178,16 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
m_process->GetID());
// The threads that are in "new_thread_list" upon entry are the threads from
- // the
- // lldb_private::Process subclass, no memory threads will be in this list.
-
- auto interpreter_lock =
- m_interpreter
- ->AcquireInterpreterLock(); // to make sure threads_list stays alive
+ // the lldb_private::Process subclass, no memory threads will be in this
+ // list.
StructuredData::ArraySP threads_list =
m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp);
const uint32_t num_cores = core_thread_list.GetSize(false);
// Make a map so we can keep track of which cores were used from the
- // core_thread list. Any real threads/cores that weren't used should
- // later be put back into the "new_thread_list".
+ // core_thread list. Any real threads/cores that weren't used should later be
+ // put back into the "new_thread_list".
std::vector<bool> core_used_map(num_cores, false);
if (threads_list) {
if (log) {
@@ -214,8 +212,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
// Any real core threads that didn't end up backing a memory thread should
// still be in the main thread list, and they should be inserted at the
- // beginning
- // of the list
+ // beginning of the list
uint32_t insert_idx = 0;
for (uint32_t core_idx = 0; core_idx < num_cores; ++core_idx) {
if (core_used_map[core_idx] == false) {
@@ -256,8 +253,8 @@ ThreadSP OperatingSystemPython::CreateThreadFromThreadInfo(
// plug-in generated thread.
if (!IsOperatingSystemPluginThread(thread_sp)) {
// We have thread ID overlap between the protocol threads and the
- // operating system threads, clear the thread so we create an
- // operating system thread for this.
+ // operating system threads, clear the thread so we create an operating
+ // system thread for this.
thread_sp.reset();
}
}
@@ -301,20 +298,24 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
return reg_ctx_sp;
- // First thing we have to do is get the API lock, and the run lock. We're
- // going to change the thread
- // content of the process, and we're going to use python, which requires the
- // API lock to do it.
- // So get & hold that. This is a recursive lock so we can grant it to any
- // Python code called on the stack below us.
+ // First thing we have to do is to try to get the API lock, and the
+ // interpreter lock. We're going to change the thread content of the process,
+ // and we're going to use python, which requires the API lock to do it. We
+ // need the interpreter lock to make sure thread_info_dict stays alive.
+ //
+ // If someone already has the API lock, that is ok, we just want to avoid
+ // external code from making new API calls while this call is happening.
+ //
+ // This is a recursive lock so we can grant it to any Python code called on
+ // the stack below us.
Target &target = m_process->GetTarget();
- std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex());
+ std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
+ std::defer_lock);
+ api_lock.try_lock();
+ auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
- auto lock =
- m_interpreter
- ->AcquireInterpreterLock(); // to make sure python objects stays alive
if (reg_data_addr != LLDB_INVALID_ADDRESS) {
// The registers data is in contiguous memory, just create the register
// context using the address provided
@@ -326,8 +327,8 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
reg_ctx_sp.reset(new RegisterContextMemory(
*thread, 0, *GetDynamicRegisterInfo(), reg_data_addr));
} else {
- // No register data address is provided, query the python plug-in to let
- // it make up the data as it sees fit
+ // No register data address is provided, query the python plug-in to let it
+ // make up the data as it sees fit
if (log)
log->Printf("OperatingSystemPython::CreateRegisterContextForThread (tid "
"= 0x%" PRIx64 ", 0x%" PRIx64
@@ -383,18 +384,23 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
tid, context);
if (m_interpreter && m_python_object_sp) {
- // First thing we have to do is get the API lock, and the run lock. We're
- // going to change the thread
- // content of the process, and we're going to use python, which requires the
- // API lock to do it.
- // So get & hold that. This is a recursive lock so we can grant it to any
- // Python code called on the stack below us.
+ // First thing we have to do is to try to get the API lock, and the
+ // interpreter lock. We're going to change the thread content of the
+ // process, and we're going to use python, which requires the API lock to
+ // do it. We need the interpreter lock to make sure thread_info_dict stays
+ // alive.
+ //
+ // If someone already has the API lock, that is ok, we just want to avoid
+ // external code from making new API calls while this call is happening.
+ //
+ // This is a recursive lock so we can grant it to any Python code called on
+ // the stack below us.
Target &target = m_process->GetTarget();
- std::lock_guard<std::recursive_mutex> guard(target.GetAPIMutex());
+ std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
+ std::defer_lock);
+ api_lock.try_lock();
+ auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
- auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure
- // thread_info_dict
- // stays alive
StructuredData::DictionarySP thread_info_dict =
m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context);
std::vector<bool> core_used_map;
diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp
index 6e15eb2b1dcb..4cd8c645dd76 100644
--- a/source/Plugins/Platform/Android/AdbClient.cpp
+++ b/source/Plugins/Platform/Android/AdbClient.cpp
@@ -165,8 +165,8 @@ Status AdbClient::GetDevices(DeviceIDList &device_list) {
for (const auto device : devices)
device_list.push_back(device.split('\t').first);
- // Force disconnect since ADB closes connection after host:devices
- // response is sent.
+ // Force disconnect since ADB closes connection after host:devices response
+ // is sent.
m_conn.reset();
return error;
}
diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp
index 5b85bcdf7fdd..1cedcde97a92 100644
--- a/source/Plugins/Platform/Android/PlatformAndroid.cpp
+++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -83,9 +83,9 @@ PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__ANDROID__)
- // Only accept "unknown" for the vendor if the host is android and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified_
+ // Only accept "unknown" for the vendor if the host is android and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified_
case llvm::Triple::VendorType::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
@@ -100,9 +100,9 @@ PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__ANDROID__)
- // Only accept "unknown" for the OS if the host is android and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is android and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -193,8 +193,7 @@ Status PlatformAndroid::GetFile(const FileSpec &source,
if (IsHost() || !m_remote_platform_sp)
return PlatformLinux::GetFile(source, destination);
- FileSpec source_spec(source.GetPath(false), false,
- FileSpec::ePathSyntaxPosix);
+ FileSpec source_spec(source.GetPath(false), false, FileSpec::Style::posix);
if (source_spec.IsRelative())
source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
source_spec.GetCString(false));
@@ -222,8 +221,8 @@ Status PlatformAndroid::GetFile(const FileSpec &source,
if (strchr(source_file, '\'') != nullptr)
return Status("Doesn't support single-quotes in filenames");
- // mode == 0 can signify that adbd cannot access the file
- // due security constraints - try "cat ..." as a fallback.
+ // mode == 0 can signify that adbd cannot access the file due security
+ // constraints - try "cat ..." as a fallback.
AdbClient adb(m_device_id);
char cmd[PATH_MAX];
@@ -239,7 +238,7 @@ Status PlatformAndroid::PutFile(const FileSpec &source,
return PlatformLinux::PutFile(source, destination, uid, gid);
FileSpec destination_spec(destination.GetPath(false), false,
- FileSpec::ePathSyntaxPosix);
+ FileSpec::Style::posix);
if (destination_spec.IsRelative())
destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
destination_spec.GetCString(false));
@@ -306,7 +305,7 @@ Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
const FileSpec &dst_file_spec) {
// For oat file we can try to fetch additional debug info from the device
ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
- if (extension != ConstString("oat") && extension != ConstString("odex"))
+ if (extension != ConstString(".oat") && extension != ConstString(".odex"))
return Status(
"Symbol file downloading only supported for oat and odex files");
@@ -361,10 +360,8 @@ Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
}
bool PlatformAndroid::GetRemoteOSVersion() {
- m_major_os_version = GetSdkVersion();
- m_minor_os_version = 0;
- m_update_os_version = 0;
- return m_major_os_version != 0;
+ m_os_version = llvm::VersionTuple(GetSdkVersion());
+ return !m_os_version.empty();
}
llvm::StringRef
diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
index dbc74833e287..2415da31daf0 100644
--- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -180,9 +180,9 @@ Status PlatformAndroidRemoteGDBServer::MakeConnectURL(
static const int kAttempsNum = 5;
Status error;
- // There is a race possibility that somebody will occupy
- // a port while we're in between FindUnusedPort and ForwardPortWithAdb -
- // adding the loop to mitigate such problem.
+ // There is a race possibility that somebody will occupy a port while we're
+ // in between FindUnusedPort and ForwardPortWithAdb - adding the loop to
+ // mitigate such problem.
for (auto i = 0; i < kAttempsNum; ++i) {
uint16_t local_port = 0;
error = FindUnusedPort(local_port);
@@ -208,10 +208,9 @@ lldb::ProcessSP PlatformAndroidRemoteGDBServer::ConnectProcess(
lldb_private::Debugger &debugger, lldb_private::Target *target,
lldb_private::Status &error) {
// We don't have the pid of the remote gdbserver when it isn't started by us
- // but we still want
- // to store the list of port forwards we set up in our port forward map.
- // Generate a fake pid for
- // these cases what won't collide with any other valid pid on android.
+ // but we still want to store the list of port forwards we set up in our port
+ // forward map. Generate a fake pid for these cases what won't collide with
+ // any other valid pid on android.
static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL;
int remote_port;
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 73c7d21f0a06..bc8111d1078b 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -32,8 +32,8 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
-// Define these constants from FreeBSD mman.h for use when targeting
-// remote FreeBSD systems even when host has different values.
+// Define these constants from FreeBSD mman.h for use when targeting remote
+// FreeBSD systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000
@@ -60,9 +60,8 @@ PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__FreeBSD__)
- // Only accept "unknown" for the OS if the host is BSD and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is BSD and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -143,7 +142,8 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
- // If the default host architecture is 64-bit, look for a 32-bit variant
+ // If the default host architecture is 64-bit, look for a 32-bit
+ // variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
@@ -187,13 +187,10 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
- // vendor by
- // calling triple.SetVendorName("unknown") so that it is a "unspecified
- // unknown".
- // This means when someone calls triple.GetVendorName() it will return an
- // empty string
- // which indicates that the vendor can be set when two architectures are
- // merged
+ // vendor by calling triple.SetVendorName("unknown") so that it is a
+ // "unspecified unknown". This means when someone calls
+ // triple.GetVendorName() it will return an empty string which indicates
+ // that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
@@ -228,16 +225,16 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target,
switch (target.GetArchitecture().GetMachine()) {
case llvm::Triple::arm: {
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = eAddressClassUnknown;
+ AddressClass addr_class = AddressClass::eUnknown;
if (bp_loc_sp) {
addr_class = bp_loc_sp->GetAddress().GetAddressClass();
- if (addr_class == eAddressClassUnknown &&
+ if (addr_class == AddressClass::eUnknown &&
(bp_loc_sp->GetAddress().GetFileAddress() & 1))
- addr_class = eAddressClassCodeAlternateISA;
+ addr_class = AddressClass::eCodeAlternateISA;
}
- if (addr_class == eAddressClassCodeAlternateISA) {
+ if (addr_class == AddressClass::eCodeAlternateISA) {
// TODO: Enable when FreeBSD supports thumb breakpoints.
// FreeBSD kernel as of 10.x, does not support thumb breakpoints
return 0;
@@ -286,9 +283,9 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
if (target && error.Success()) {
debugger.GetTargetList().SetSelectedTarget(target);
- // The freebsd always currently uses the GDB remote debugger plug-in
- // so even when debugging locally we are debugging remotely!
- // Just like the darwin plugin.
+ // The freebsd always currently uses the GDB remote debugger plug-in so
+ // even when debugging locally we are debugging remotely! Just like the
+ // darwin plugin.
process_sp = target->CreateProcess(
attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp
index 8186eae0e8c4..dbde91d7ab2d 100644
--- a/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -30,8 +30,8 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
-// Define these constants from Linux mman.h for use when targeting
-// remote linux systems even when host has different values.
+// Define these constants from Linux mman.h for use when targeting remote linux
+// systems even when host has different values.
#define MAP_PRIVATE 2
#define MAP_ANON 0x20
@@ -58,9 +58,8 @@ PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__linux__)
- // Only accept "unknown" for the OS if the host is linux and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is linux and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -142,7 +141,8 @@ bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx,
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
- // If the default host architecture is 64-bit, look for a 32-bit variant
+ // If the default host architecture is 64-bit, look for a 32-bit
+ // variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
@@ -192,13 +192,10 @@ bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
- // vendor by
- // calling triple.SetVendorName("unknown") so that it is a "unspecified
- // unknown".
- // This means when someone calls triple.GetVendorName() it will return an
- // empty string
- // which indicates that the vendor can be set when two architectures are
- // merged
+ // vendor by calling triple.SetVendorName("unknown") so that it is a
+ // "unspecified unknown". This means when someone calls
+ // triple.GetVendorName() it will return an empty string which indicates
+ // that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
@@ -212,8 +209,8 @@ void PlatformLinux::GetStatus(Stream &strm) {
#ifndef LLDB_DISABLE_POSIX
// Display local kernel information only when we are running in host mode.
- // Otherwise, we would end up printing non-Linux information (when running
- // on Mac OS for example).
+ // Otherwise, we would end up printing non-Linux information (when running on
+ // Mac OS for example).
if (IsHost()) {
struct utsname un;
@@ -272,8 +269,8 @@ bool PlatformLinux::CanDebugProcess() {
}
// For local debugging, Linux will override the debug logic to use llgs-launch
-// rather than lldb-launch, llgs-attach. This differs from current lldb-launch,
-// debugserver-attach approach on MacOSX.
+// rather than lldb-launch, llgs-attach. This differs from current lldb-
+// launch, debugserver-attach approach on MacOSX.
lldb::ProcessSP
PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new
@@ -297,8 +294,8 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
launch_info.GetFlags().Set(eLaunchFlagDebug);
// We always launch the process we are going to debug in a separate process
- // group, since then we can handle ^C interrupts ourselves w/o having to worry
- // about the target getting them as well.
+ // group, since then we can handle ^C interrupts ourselves w/o having to
+ // worry about the target getting them as well.
launch_info.SetLaunchInSeparateProcessGroup(true);
// Ensure we have a target.
diff --git a/source/Plugins/Platform/MacOSX/CMakeLists.txt b/source/Plugins/Platform/MacOSX/CMakeLists.txt
index f8d911b321f8..f9663559069a 100644
--- a/source/Plugins/Platform/MacOSX/CMakeLists.txt
+++ b/source/Plugins/Platform/MacOSX/CMakeLists.txt
@@ -11,13 +11,14 @@ list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
list(APPEND PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES
PlatformAppleSimulator.cpp
PlatformiOSSimulator.cpp
- PlatformiOSSimulatorCoreSimulatorSupport.mm
PlatformAppleTVSimulator.cpp
PlatformAppleWatchSimulator.cpp
)
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
include_directories(${LIBXML2_INCLUDE_DIR})
+ add_subdirectory(objcxx)
+ set(OBJC_LIBS "lldbPluginPlatformMacOSXObjCXX")
list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
${PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES})
else()
@@ -38,6 +39,7 @@ add_lldb_library(lldbPluginPlatformMacOSX PLUGIN
lldbTarget
lldbUtility
lldbPluginPlatformPOSIX
+ ${OBJC_LIBS}
LINK_COMPONENTS
Support
)
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
index a216e3839dd9..6852097117a1 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
@@ -84,8 +84,8 @@ lldb_private::Status PlatformAppleSimulator::LaunchProcess(
void PlatformAppleSimulator::GetStatus(Stream &strm) {
#if defined(__APPLE__)
- // This will get called by subclasses, so just output status on the
- // current simulator
+ // This will get called by subclasses, so just output status on the current
+ // simulator
PlatformAppleSimulator::LoadCoreSimulator();
CoreSimulatorSupport::DeviceSet devices =
@@ -183,8 +183,8 @@ lldb::ProcessSP PlatformAppleSimulator::DebugProcess(
// Make sure we stop at the entry point
launch_info.GetFlags().Set(eLaunchFlagDebug);
// We always launch the process we are going to debug in a separate process
- // group, since then we can handle ^C interrupts ourselves w/o having to worry
- // about the target getting them as well.
+ // group, since then we can handle ^C interrupts ourselves w/o having to
+ // worry about the target getting them as well.
launch_info.SetLaunchInSeparateProcessGroup(true);
error = LaunchProcess(launch_info);
@@ -201,10 +201,10 @@ lldb::ProcessSP PlatformAppleSimulator::DebugProcess(
// process if this happens.
process_sp->SetShouldDetach(false);
- // If we didn't have any file actions, the pseudo terminal might
- // have been used where the slave side was given as the file to
- // open for stdin/out/err after we have already opened the master
- // so we can read/write stdin/out/err.
+ // If we didn't have any file actions, the pseudo terminal might have
+ // been used where the slave side was given as the file to open for
+ // stdin/out/err after we have already opened the master so we can
+ // read/write stdin/out/err.
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
index 44feb019dc73..2536854e9630 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
@@ -16,8 +16,8 @@
// Other libraries and framework includes
// Project includes
-#include "PlatformDarwin.h"
-#include "PlatformiOSSimulatorCoreSimulatorSupport.h"
+#include "Plugins/Platform/MacOSX/PlatformDarwin.h"
+#include "Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/ADT/Optional.h"
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
index e0558f8b200e..e55cc0f4f6a4 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
@@ -90,9 +90,9 @@ PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force,
break;
#if defined(__APPLE__)
- // Only accept "unknown" for the vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the vendor if the host is Apple and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
@@ -107,9 +107,9 @@ PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force,
break;
#if defined(__APPLE__)
- // Only accept "unknown" for the OS if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is Apple and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -199,9 +199,9 @@ Status PlatformAppleTVSimulator::ResolveExecutable(
return error;
exe_module_sp.reset();
}
- // No valid architecture was specified or the exact ARM slice wasn't
- // found so ask the platform for the architectures that we should be
- // using (in the correct order) and see if we can find a match that way
+ // No valid architecture was specified or the exact ARM slice wasn't found
+ // so ask the platform for the architectures that we should be using (in
+ // the correct order) and see if we can find a match that way
StreamString arch_names;
ArchSpec platform_arch;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
@@ -293,8 +293,8 @@ const char *PlatformAppleTVSimulator::GetSDKDirectoryAsCString() {
m_sdk_directory.assign(1, '\0');
}
- // We should have put a single NULL character into m_sdk_directory
- // or it should have a valid path if the code gets here
+ // We should have put a single NULL character into m_sdk_directory or it
+ // should have a valid path if the code gets here
assert(m_sdk_directory.empty() == false);
if (m_sdk_directory[0])
return m_sdk_directory.c_str();
@@ -315,12 +315,12 @@ Status PlatformAppleTVSimulator::GetSymbolFile(const FileSpec &platform_file,
platform_file_path);
// First try in the SDK and see if the file is in there
- local_file.SetFile(resolved_path, true);
+ local_file.SetFile(resolved_path, true, FileSpec::Style::native);
if (local_file.Exists())
return error;
// Else fall back to the actual path itself
- local_file.SetFile(platform_file_path, true);
+ local_file.SetFile(platform_file_path, true, FileSpec::Style::native);
if (local_file.Exists())
return error;
}
@@ -337,10 +337,9 @@ Status PlatformAppleTVSimulator::GetSharedModule(
const ModuleSpec &module_spec, lldb_private::Process *process,
ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
- // For AppleTV, the SDK files are all cached locally on the host
- // system. So first we ask for the file in the cached SDK,
- // then we attempt to get a shared module for the right architecture
- // with the right UUID.
+ // For AppleTV, the SDK files are all cached locally on the host system. So
+ // first we ask for the file in the cached SDK, then we attempt to get a
+ // shared module for the right architecture with the right UUID.
Status error;
ModuleSpec platform_module_spec(module_spec);
const FileSpec &platform_file = module_spec.GetFileSpec();
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
index 9b2608f68625..8bbe0af0aec2 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
@@ -89,9 +89,9 @@ PlatformSP PlatformAppleWatchSimulator::CreateInstance(bool force,
break;
#if defined(__APPLE__)
- // Only accept "unknown" for the vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the vendor if the host is Apple and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
@@ -106,9 +106,9 @@ PlatformSP PlatformAppleWatchSimulator::CreateInstance(bool force,
break;
#if defined(__APPLE__)
- // Only accept "unknown" for the OS if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is Apple and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -199,9 +199,9 @@ Status PlatformAppleWatchSimulator::ResolveExecutable(
return error;
exe_module_sp.reset();
}
- // No valid architecture was specified or the exact ARM slice wasn't
- // found so ask the platform for the architectures that we should be
- // using (in the correct order) and see if we can find a match that way
+ // No valid architecture was specified or the exact ARM slice wasn't found
+ // so ask the platform for the architectures that we should be using (in
+ // the correct order) and see if we can find a match that way
StreamString arch_names;
ArchSpec platform_arch;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
@@ -293,8 +293,8 @@ const char *PlatformAppleWatchSimulator::GetSDKDirectoryAsCString() {
m_sdk_directory.assign(1, '\0');
}
- // We should have put a single NULL character into m_sdk_directory
- // or it should have a valid path if the code gets here
+ // We should have put a single NULL character into m_sdk_directory or it
+ // should have a valid path if the code gets here
assert(m_sdk_directory.empty() == false);
if (m_sdk_directory[0])
return m_sdk_directory.c_str();
@@ -315,12 +315,12 @@ Status PlatformAppleWatchSimulator::GetSymbolFile(const FileSpec &platform_file,
platform_file_path);
// First try in the SDK and see if the file is in there
- local_file.SetFile(resolved_path, true);
+ local_file.SetFile(resolved_path, true, FileSpec::Style::native);
if (local_file.Exists())
return error;
// Else fall back to the actual path itself
- local_file.SetFile(platform_file_path, true);
+ local_file.SetFile(platform_file_path, true, FileSpec::Style::native);
if (local_file.Exists())
return error;
}
@@ -337,10 +337,9 @@ Status PlatformAppleWatchSimulator::GetSharedModule(
const ModuleSpec &module_spec, lldb_private::Process *process,
ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr,
ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
- // For AppleWatch, the SDK files are all cached locally on the host
- // system. So first we ask for the file in the cached SDK,
- // then we attempt to get a shared module for the right architecture
- // with the right UUID.
+ // For AppleWatch, the SDK files are all cached locally on the host system.
+ // So first we ask for the file in the cached SDK, then we attempt to get a
+ // shared module for the right architecture with the right UUID.
Status error;
ModuleSpec platform_module_spec(module_spec);
const FileSpec &platform_file = module_spec.GetFileSpec();
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index b04d72f755f6..886e3b6d9a05 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -16,8 +16,6 @@
#include <algorithm>
#include <mutex>
-// Other libraries and framework includes
-#include "clang/Basic/VersionTuple.h"
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
@@ -42,6 +40,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Threading.h"
+#include "llvm/Support/VersionTuple.h"
#if defined(__APPLE__)
#include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
@@ -73,10 +72,9 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
// NB some extensions might be meaningful and should not be stripped -
// "this.binary.file"
// should not lose ".file" but GetFileNameStrippingExtension() will do
- // precisely that.
- // Ideally, we should have a per-platform list of extensions (".exe",
- // ".app", ".dSYM", ".framework")
- // which should be stripped while leaving "this.binary.file" as-is.
+ // precisely that. Ideally, we should have a per-platform list of
+ // extensions (".exe", ".app", ".dSYM", ".framework") which should be
+ // stripped while leaving "this.binary.file" as-is.
ScriptInterpreter *script_interpreter =
target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
@@ -101,14 +99,11 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
// FIXME: for Python, we cannot allow certain characters in
// module
// filenames we import. Theoretically, different scripting
- // languages may
- // have different sets of forbidden tokens in filenames, and
- // that should
- // be dealt with by each ScriptInterpreter. For now, we just
- // replace dots
- // with underscores, but if we ever support anything other than
- // Python
- // we will need to rework this
+ // languages may have different sets of forbidden tokens in
+ // filenames, and that should be dealt with by each
+ // ScriptInterpreter. For now, we just replace dots with
+ // underscores, but if we ever support anything other than
+ // Python we will need to rework this
std::replace(module_basename.begin(), module_basename.end(),
'.', '_');
std::replace(module_basename.begin(), module_basename.end(),
@@ -125,9 +120,9 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
StreamString path_string;
StreamString original_path_string;
// for OSX we are going to be in
- // .dSYM/Contents/Resources/DWARF/<basename>
- // let us go to .dSYM/Contents/Resources/Python/<basename>.py
- // and see if the file exists
+ // .dSYM/Contents/Resources/DWARF/<basename> let us go to
+ // .dSYM/Contents/Resources/Python/<basename>.py and see if the
+ // file exists
path_string.Printf("%s/../Python/%s.py",
symfile_spec.GetDirectory().GetCString(),
module_basename.c_str());
@@ -140,9 +135,8 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
true);
// if we did some replacements of reserved characters, and a
- // file with the untampered name
- // exists, then warn the user that the file as-is shall not be
- // loaded
+ // file with the untampered name exists, then warn the user
+ // that the file as-is shall not be loaded
if (feedback_stream) {
if (module_basename != original_module_basename &&
orig_script_fspec.Exists()) {
@@ -178,8 +172,8 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
break;
}
- // If we didn't find the python file, then keep
- // stripping the extensions and try again
+ // If we didn't find the python file, then keep stripping the
+ // extensions and try again
ConstString filename_no_extension(
module_spec.GetFileNameStrippingExtension());
if (module_spec.GetFilename() == filename_no_extension)
@@ -270,8 +264,8 @@ lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache(
FileSpec module_cache_spec(cache_path, false);
// if rsync is supported, always bring in the file - rsync will be very
- // efficient
- // when files are the same on the local and remote end of the connection
+ // efficient when files are the same on the local and remote end of the
+ // connection
if (this->GetSupportsRSync()) {
err = BringInRemoteFile(this, module_spec, module_cache_spec);
if (err.Fail())
@@ -370,8 +364,8 @@ Status PlatformDarwin::GetSharedModule(
module_sp.reset();
if (IsRemote()) {
- // If we have a remote platform always, let it try and locate
- // the shared module first.
+ // If we have a remote platform always, let it try and locate the shared
+ // module first.
if (m_remote_platform_sp) {
error = m_remote_platform_sp->GetSharedModule(
module_spec, process, module_sp, module_search_paths_ptr,
@@ -453,8 +447,8 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target,
switch (machine) {
case llvm::Triple::aarch64: {
// TODO: fix this with actual darwin breakpoint opcode for arm64.
- // right now debugging uses the Z packets with GDB remote so this
- // is not needed, but the size needs to be correct...
+ // right now debugging uses the Z packets with GDB remote so this is not
+ // needed, but the size needs to be correct...
static const uint8_t g_arm64_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7};
trap_opcode = g_arm64_breakpoint_opcode;
trap_opcode_size = sizeof(g_arm64_breakpoint_opcode);
@@ -472,7 +466,7 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target,
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
if (bp_loc_sp)
bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() ==
- eAddressClassCodeAlternateISA;
+ AddressClass::eCodeAlternateISA;
}
if (bp_is_thumb) {
trap_opcode = g_thumb_breakpooint_opcode;
@@ -548,8 +542,8 @@ bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx,
HostInfo::GetArchitecture(HostInfo::eArchKind64));
if (platform_arch.IsExactMatch(platform_arch64)) {
// This macosx platform supports both 32 and 64 bit. Since we already
- // returned the 64 bit arch for idx == 0, return the 32 bit arch
- // for idx == 1
+ // returned the 64 bit arch for idx == 0, return the 32 bit arch for
+ // idx == 1
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
}
@@ -558,9 +552,9 @@ bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
-// The architecture selection rules for arm processors
-// These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run
-// fine on an armv7f processor.
+// The architecture selection rules for arm processors These cpu subtypes have
+// distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f
+// processor.
bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
@@ -1138,14 +1132,15 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
if (m_developer_directory.empty()) {
bool developer_dir_path_valid = false;
char developer_dir_path[PATH_MAX];
- FileSpec temp_file_spec;
// Get the lldb framework's file path, and if it exists, truncate some
// components to only the developer directory path.
- if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, temp_file_spec)) {
+ FileSpec temp_file_spec = HostInfo::GetShlibDir();
+ if (temp_file_spec) {
if (temp_file_spec.GetPath(developer_dir_path,
sizeof(developer_dir_path))) {
- // e.g. /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework
+ // e.g.
+ // /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework
char *shared_frameworks =
strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework");
if (shared_frameworks) {
@@ -1153,7 +1148,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
strncat (developer_dir_path, "/Developer", sizeof (developer_dir_path) - 1); // add /Developer on
developer_dir_path_valid = true;
} else {
- // e.g. /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework
+ // e.g.
+ // /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework
char *developer_toolchains =
strstr(developer_dir_path, "/Contents/Developer/Toolchains/");
if (developer_toolchains) {
@@ -1171,7 +1167,7 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
if (xcode_select_prefix_dir)
xcode_dir_path.append(xcode_select_prefix_dir);
xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path");
- temp_file_spec.SetFile(xcode_dir_path, false);
+ temp_file_spec.SetFile(xcode_dir_path, false, FileSpec::Style::native);
auto dir_buffer =
DataBufferLLVM::CreateFromPath(temp_file_spec.GetPath());
if (dir_buffer && dir_buffer->GetByteSize() > 0) {
@@ -1196,7 +1192,7 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
Host::RunShellCommand("/usr/bin/xcode-select --print-path",
NULL, // current working directory
&exit_status, &signo, &command_output,
- 2, // short timeout
+ std::chrono::seconds(2), // short timeout
false); // don't run in a shell
if (error.Success() && exit_status == 0 && !command_output.empty()) {
const char *cmd_output_ptr = command_output.c_str();
@@ -1219,7 +1215,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
}
if (developer_dir_path_valid) {
- temp_file_spec.SetFile(developer_dir_path, false);
+ temp_file_spec.SetFile(developer_dir_path, false,
+ FileSpec::Style::native);
if (temp_file_spec.Exists()) {
m_developer_directory.assign(developer_dir_path);
return m_developer_directory.c_str();
@@ -1230,8 +1227,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
m_developer_directory.assign(1, '\0');
}
- // We should have put a single NULL character into m_developer_directory
- // or it should have a valid path if the code gets here
+ // We should have put a single NULL character into m_developer_directory or
+ // it should have a valid path if the code gets here
assert(m_developer_directory.empty() == false);
if (m_developer_directory[0])
return m_developer_directory.c_str();
@@ -1279,17 +1276,11 @@ PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
shell_name++;
if (strcmp(shell_name, "sh") == 0) {
- // /bin/sh re-exec's itself as /bin/bash requiring another resume.
- // But it only does this if the COMMAND_MODE environment variable
- // is set to "legacy".
- const char **envp =
- launch_info.GetEnvironmentEntries().GetConstArgumentVector();
- if (envp != NULL) {
- for (int i = 0; envp[i] != NULL; i++) {
- if (strcmp(envp[i], "COMMAND_MODE=legacy") == 0)
- return 2;
- }
- }
+ // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it
+ // only does this if the COMMAND_MODE environment variable is set to
+ // "legacy".
+ if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy")
+ return 2;
return 1;
} else if (strcmp(shell_name, "csh") == 0 ||
strcmp(shell_name, "tcsh") == 0 ||
@@ -1310,7 +1301,7 @@ static const char *const sdk_strings[] = {
static FileSpec CheckPathForXcode(const FileSpec &fspec) {
if (fspec.Exists()) {
- const char substr[] = ".app/Contents/";
+ const char substr[] = ".app/Contents";
std::string path_to_shlib = fspec.GetPath();
size_t pos = path_to_shlib.rfind(substr);
@@ -1339,9 +1330,8 @@ static FileSpec GetXcodeContentsPath() {
// First get the program file spec. If lldb.so or LLDB.framework is running
// in a program and that program is Xcode, the path returned with be the
- // path
- // to Xcode.app/Contents/MacOS/Xcode, so this will be the correct Xcode to
- // use.
+ // path to Xcode.app/Contents/MacOS/Xcode, so this will be the correct
+ // Xcode to use.
fspec = HostInfo::GetProgramFileSpec();
if (fspec) {
@@ -1375,7 +1365,7 @@ static FileSpec GetXcodeContentsPath() {
&signo, // Put the signal that caused the process to exit in here
&output, // Get the output from the command and place it in this
// string
- 3); // Timeout in seconds to wait for shell program to finish
+ std::chrono::seconds(3));
if (status == 0 && !output.empty()) {
size_t first_non_newline = output.find_last_not_of("\r\n");
if (first_non_newline != std::string::npos) {
@@ -1392,18 +1382,14 @@ static FileSpec GetXcodeContentsPath() {
return g_xcode_filespec;
}
-bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type, uint32_t major,
- uint32_t minor, uint32_t micro) {
+bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type,
+ llvm::VersionTuple version) {
switch (sdk_type) {
case SDKType::MacOSX:
- if (major > 10 || (major == 10 && minor >= 10))
- return true;
- break;
+ return version >= llvm::VersionTuple(10, 10);
case SDKType::iPhoneOS:
case SDKType::iPhoneSimulator:
- if (major >= 8)
- return true;
- break;
+ return version >= llvm::VersionTuple(8);
}
return false;
@@ -1425,32 +1411,10 @@ bool PlatformDarwin::SDKSupportsModules(SDKType desired_type,
return false;
}
- const size_t major_dot_offset = version_part.find('.');
- if (major_dot_offset == llvm::StringRef::npos)
- return false;
-
- const llvm::StringRef major_version =
- version_part.slice(0, major_dot_offset);
- const llvm::StringRef minor_part =
- version_part.drop_front(major_dot_offset + 1);
-
- const size_t minor_dot_offset = minor_part.find('.');
- if (minor_dot_offset == llvm::StringRef::npos)
- return false;
-
- const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset);
-
- unsigned int major = 0;
- unsigned int minor = 0;
- unsigned int micro = 0;
-
- if (major_version.getAsInteger(10, major))
- return false;
-
- if (minor_version.getAsInteger(10, minor))
+ llvm::VersionTuple version;
+ if (version.tryParse(version_part))
return false;
-
- return SDKSupportsModules(desired_type, major, minor, micro);
+ return SDKSupportsModules(desired_type, version);
}
return false;
@@ -1522,18 +1486,17 @@ FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
sdks_spec.AppendPathComponent("SDKs");
if (sdk_type == SDKType::MacOSX) {
- uint32_t major = 0;
- uint32_t minor = 0;
- uint32_t micro = 0;
+ llvm::VersionTuple version = HostInfo::GetOSVersion();
- if (HostInfo::GetOSVersion(major, minor, micro)) {
- if (SDKSupportsModules(SDKType::MacOSX, major, minor, micro)) {
+ if (!version.empty()) {
+ if (SDKSupportsModules(SDKType::MacOSX, version)) {
// We slightly prefer the exact SDK for this machine. See if it is
// there.
FileSpec native_sdk_spec = sdks_spec;
StreamString native_sdk_name;
- native_sdk_name.Printf("MacOSX%u.%u.sdk", major, minor);
+ native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(),
+ version.getMinor().getValueOr(0));
native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
if (native_sdk_spec.Exists()) {
@@ -1546,14 +1509,14 @@ FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
return FindSDKInXcodeForModules(sdk_type, sdks_spec);
}
-std::tuple<uint32_t, uint32_t, uint32_t, llvm::StringRef>
+std::tuple<llvm::VersionTuple, llvm::StringRef>
PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
- uint32_t major, minor, update;
llvm::StringRef build;
llvm::StringRef version_str;
llvm::StringRef build_str;
std::tie(version_str, build_str) = dir.split(' ');
- if (Args::StringToVersion(version_str, major, minor, update) ||
+ llvm::VersionTuple version;
+ if (!version.tryParse(version_str) ||
build_str.empty()) {
if (build_str.consume_front("(")) {
size_t pos = build_str.find(')');
@@ -1561,7 +1524,7 @@ PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
}
}
- return std::make_tuple(major, minor, update, build);
+ return std::make_tuple(version, build);
}
void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
@@ -1573,7 +1536,6 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
options.insert(options.end(), apple_arguments.begin(), apple_arguments.end());
StreamString minimum_version_option;
- uint32_t versions[3] = {0, 0, 0};
bool use_current_os_version = false;
switch (sdk_type) {
case SDKType::iPhoneOS:
@@ -1597,9 +1559,9 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
break;
}
- bool versions_valid = false;
+ llvm::VersionTuple version;
if (use_current_os_version)
- versions_valid = GetOSVersion(versions[0], versions[1], versions[2]);
+ version = GetOSVersion();
else if (target) {
// Our OS doesn't match our executable so we need to get the min OS version
// from the object file
@@ -1607,35 +1569,23 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
if (exe_module_sp) {
ObjectFile *object_file = exe_module_sp->GetObjectFile();
if (object_file)
- versions_valid = object_file->GetMinimumOSVersion(versions, 3) > 0;
+ version = object_file->GetMinimumOSVersion();
}
}
// Only add the version-min options if we got a version from somewhere
- if (versions_valid && versions[0] != UINT32_MAX) {
- // Make any invalid versions be zero if needed
- if (versions[1] == UINT32_MAX)
- versions[1] = 0;
- if (versions[2] == UINT32_MAX)
- versions[2] = 0;
-
+ if (!version.empty()) {
switch (sdk_type) {
case SDKType::iPhoneOS:
minimum_version_option.PutCString("-mios-version-min=");
- minimum_version_option.PutCString(
- clang::VersionTuple(versions[0], versions[1], versions[2])
- .getAsString());
+ minimum_version_option.PutCString(version.getAsString());
break;
case SDKType::iPhoneSimulator:
minimum_version_option.PutCString("-mios-simulator-version-min=");
- minimum_version_option.PutCString(
- clang::VersionTuple(versions[0], versions[1], versions[2])
- .getAsString());
+ minimum_version_option.PutCString(version.getAsString());
break;
case SDKType::MacOSX:
minimum_version_option.PutCString("-mmacosx-version-min=");
- minimum_version_option.PutCString(
- clang::VersionTuple(versions[0], versions[1], versions[2])
- .getAsString());
+ minimum_version_option.PutCString(version.getAsString());
}
options.push_back(minimum_version_option.GetString());
}
@@ -1662,49 +1612,35 @@ ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) {
return ConstString(stream.GetString());
}
-bool PlatformDarwin::GetOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update, Process *process) {
+llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) {
if (process && strstr(GetPluginName().GetCString(), "-simulator")) {
lldb_private::ProcessInstanceInfo proc_info;
if (Host::GetProcessInfo(process->GetID(), proc_info)) {
- Args &env = proc_info.GetEnvironmentEntries();
- const size_t n = env.GetArgumentCount();
- const llvm::StringRef k_runtime_version("SIMULATOR_RUNTIME_VERSION=");
- const llvm::StringRef k_dyld_root_path("DYLD_ROOT_PATH=");
- std::string dyld_root_path;
-
- for (size_t i = 0; i < n; ++i) {
- const char *env_cstr = env.GetArgumentAtIndex(i);
- if (env_cstr) {
- llvm::StringRef env_str(env_cstr);
- if (env_str.consume_front(k_runtime_version)) {
- if (Args::StringToVersion(env_str, major, minor, update))
- return true;
- } else if (env_str.consume_front(k_dyld_root_path)) {
- dyld_root_path = env_str;
- }
- }
- }
+ const Environment &env = proc_info.GetEnvironment();
+ llvm::VersionTuple result;
+ if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION")))
+ return result;
+
+ std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH");
if (!dyld_root_path.empty()) {
dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
ApplePropertyList system_version_plist(dyld_root_path.c_str());
std::string product_version;
if (system_version_plist.GetValueAsString("ProductVersion",
product_version)) {
- return Args::StringToVersion(product_version, major, minor, update);
+ if (!result.tryParse(product_version))
+ return result;
}
}
}
// For simulator platforms, do NOT call back through
- // Platform::GetOSVersion()
- // as it might call Process::GetHostOSVersion() which we don't want as it
- // will be
- // incorrect
- return false;
+ // Platform::GetOSVersion() as it might call Process::GetHostOSVersion()
+ // which we don't want as it will be incorrect
+ return llvm::VersionTuple();
}
- return Platform::GetOSVersion(major, minor, update, process);
+ return Platform::GetOSVersion(process);
}
lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
@@ -1713,8 +1649,8 @@ lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
// any executable directories that should be searched.
static std::vector<FileSpec> g_executable_dirs;
- // Find the global list of directories that we will search for
- // executables once so we don't keep doing the work over and over.
+ // Find the global list of directories that we will search for executables
+ // once so we don't keep doing the work over and over.
static llvm::once_flag g_once_flag;
llvm::call_once(g_once_flag, []() {
@@ -1748,22 +1684,19 @@ lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
lldb_private::Status
PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) {
- // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr
- // if the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't
- // require any specific value; rather, it just needs to exist).
- // We will set it here as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag
- // is not set. Xcode makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
+ // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if
+ // the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't require
+ // any specific value; rather, it just needs to exist). We will set it here
+ // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set. Xcode
+ // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
// LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
// specifically want it unset.
const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE";
- auto &env_vars = launch_info.GetEnvironmentEntries();
- if (!env_vars.ContainsEnvironmentVariable(llvm::StringRef(disable_env_var))) {
- // We want to make sure that OS_ACTIVITY_DT_MODE is set so that
- // we get os_log and NSLog messages mirrored to the target process
- // stderr.
- if (!env_vars.ContainsEnvironmentVariable(
- llvm::StringRef("OS_ACTIVITY_DT_MODE")))
- env_vars.AppendArgument(llvm::StringRef("OS_ACTIVITY_DT_MODE=enable"));
+ auto &env_vars = launch_info.GetEnvironment();
+ if (!env_vars.count(disable_env_var)) {
+ // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get
+ // os_log and NSLog messages mirrored to the target process stderr.
+ env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable");
}
// Let our parent class do the real launching.
@@ -1777,24 +1710,23 @@ PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec
ModuleSP *old_module_sp_ptr, bool *did_create_ptr)
{
const FileSpec &platform_file = module_spec.GetFileSpec();
- // See if the file is present in any of the module_search_paths_ptr directories.
+ // See if the file is present in any of the module_search_paths_ptr
+ // directories.
if (!module_sp && module_search_paths_ptr && platform_file) {
- // create a vector of all the file / directory names in platform_file
- // e.g. this might be
+ // create a vector of all the file / directory names in platform_file e.g.
+ // this might be
// /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
//
- // We'll need to look in the module_search_paths_ptr directories for
- // both "UIFoundation" and "UIFoundation.framework" -- most likely the
- // latter will be the one we find there.
+ // We'll need to look in the module_search_paths_ptr directories for both
+ // "UIFoundation" and "UIFoundation.framework" -- most likely the latter
+ // will be the one we find there.
FileSpec platform_pull_apart(platform_file);
std::vector<std::string> path_parts;
- ConstString unix_root_dir("/");
- while (true) {
+ path_parts.push_back(
+ platform_pull_apart.GetLastPathComponent().AsCString());
+ while (platform_pull_apart.RemoveLastPathComponent()) {
ConstString part = platform_pull_apart.GetLastPathComponent();
- platform_pull_apart.RemoveLastPathComponent();
- if (part.IsEmpty() || part == unix_root_dir)
- break;
path_parts.push_back(part.AsCString());
}
const size_t path_parts_size = path_parts.size();
@@ -1804,25 +1736,24 @@ PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec
Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (log_verbose)
log_verbose->Printf ("PlatformRemoteDarwinDevice::GetSharedModule searching for binary in search-path %s", module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str());
- // Create a new FileSpec with this module_search_paths_ptr
- // plus just the filename ("UIFoundation"), then the parent
- // dir plus filename ("UIFoundation.framework/UIFoundation")
- // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
+ // Create a new FileSpec with this module_search_paths_ptr plus just the
+ // filename ("UIFoundation"), then the parent dir plus filename
+ // ("UIFoundation.framework/UIFoundation") etc - up to four names (to
+ // handle "Foo.framework/Contents/MacOS/Foo")
for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
// Add the components backwards. For
- // .../PrivateFrameworks/UIFoundation.framework/UIFoundation
- // path_parts is
+ // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts
+ // is
// [0] UIFoundation
// [1] UIFoundation.framework
// [2] PrivateFrameworks
//
// and if 'j' is 2, we want to append path_parts[1] and then
- // path_parts[0], aka
- // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
- // path.
+ // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the
+ // module_search_paths_ptr path.
for (int k = j; k >= 0; --k) {
path_to_try.AppendPathComponent(path_parts[k]);
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index c04318e98cae..3ad29ec1a0b9 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -69,8 +69,8 @@ public:
void CalculateTrapHandlerSymbolNames() override;
- bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update,
- lldb_private::Process *process = nullptr) override;
+ llvm::VersionTuple
+ GetOSVersion(lldb_private::Process *process = nullptr) override;
bool SupportsModules() override { return true; }
@@ -82,7 +82,7 @@ public:
lldb_private::Status
LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override;
- static std::tuple<uint32_t, uint32_t, uint32_t, llvm::StringRef>
+ static std::tuple<llvm::VersionTuple, llvm::StringRef>
ParseVersionBuildDir(llvm::StringRef str);
protected:
@@ -101,8 +101,7 @@ protected:
iPhoneOS,
};
- static bool SDKSupportsModules(SDKType sdk_type, uint32_t major,
- uint32_t minor, uint32_t micro);
+ static bool SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version);
static bool SDKSupportsModules(SDKType desired_type,
const lldb_private::FileSpec &sdk_path);
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
index e5d27fc28949..1e3216c0af5a 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -92,11 +92,9 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
}
// This is a special plugin that we don't want to activate just based on an
- // ArchSpec for normal
- // userland debugging. It is only useful in kernel debug sessions and the
- // DynamicLoaderDarwinPlugin
- // (or a user doing 'platform select') will force the creation of this
- // Platform plugin.
+ // ArchSpec for normal userland debugging. It is only useful in kernel debug
+ // sessions and the DynamicLoaderDarwinPlugin (or a user doing 'platform
+ // select') will force the creation of this Platform plugin.
if (force == false) {
if (log)
log->Printf("PlatformDarwinKernel::%s() aborting creation of platform "
@@ -115,9 +113,8 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
create = true;
break;
- // Only accept "unknown" for vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for vendor if the host is Apple and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
@@ -133,9 +130,8 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
case llvm::Triple::WatchOS:
case llvm::Triple::TvOS:
break;
- // Only accept "vendor" for vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "vendor" for vendor if the host is Apple and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -341,11 +337,9 @@ void PlatformDarwinKernel::GetStatus(Stream &strm) {
void PlatformDarwinKernel::CollectKextAndKernelDirectories() {
// Differentiate between "ios debug session" and "mac debug session" so we
- // don't index
- // kext bundles that won't be used in this debug session. If this is an ios
- // kext debug
- // session, looking in /System/Library/Extensions is a waste of stat()s, for
- // example.
+ // don't index kext bundles that won't be used in this debug session. If
+ // this is an ios kext debug session, looking in /System/Library/Extensions
+ // is a waste of stat()s, for example.
// DeveloperDirectory is something like
// "/Applications/Xcode.app/Contents/Developer"
@@ -368,9 +362,8 @@ void PlatformDarwinKernel::CollectKextAndKernelDirectories() {
AddSDKSubdirsToSearchPaths("/Volumes/KernelDebugKit");
AddSDKSubdirsToSearchPaths("/AppleInternal/Developer/KDKs");
- // The KDKs distributed from Apple installed on external
- // developer systems may be in directories like
- // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
+ // The KDKs distributed from Apple installed on external developer systems
+ // may be in directories like /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
AddSDKSubdirsToSearchPaths("/Library/Developer/KDKs");
if (m_ios_debug_session != eLazyBoolNo) {
@@ -438,8 +431,8 @@ void PlatformDarwinKernel::AddSDKSubdirsToSearchPaths(const std::string &dir) {
FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory(
void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
- static ConstString g_sdk_suffix = ConstString("sdk");
- static ConstString g_kdk_suffix = ConstString("kdk");
+ static ConstString g_sdk_suffix = ConstString(".sdk");
+ static ConstString g_kdk_suffix = ConstString(".kdk");
PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton;
if (ft == llvm::sys::fs::file_type::directory_file &&
@@ -450,9 +443,8 @@ PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory(
return FileSpec::eEnumerateDirectoryResultNext;
}
-// Recursively search trough m_search_directories looking for
-// kext and kernel binaries, adding files found to the appropriate
-// lists.
+// Recursively search trough m_search_directories looking for kext and kernel
+// binaries, adding files found to the appropriate lists.
void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() {
const uint32_t num_dirs = m_search_directories.size();
for (uint32_t i = 0; i < num_dirs; i++) {
@@ -476,13 +468,11 @@ void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() {
}
}
-// We're only doing a filename match here. We won't try opening the file to see
-// if it's really
-// a kernel or not until we need to find a kernel of a given UUID. There's no
-// cheap way to find
-// the UUID of a file (or if it's a Mach-O binary at all) without creating a
-// whole Module for
-// the file and throwing it away if it's not wanted.
+// We're only doing a filename match here. We won't try opening the file to
+// see if it's really a kernel or not until we need to find a kernel of a given
+// UUID. There's no cheap way to find the UUID of a file (or if it's a Mach-O
+// binary at all) without creating a whole Module for the file and throwing it
+// away if it's not wanted.
//
// Recurse into any subdirectories found.
@@ -502,8 +492,8 @@ FileSpec::EnumerateDirectoryResult
PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec,
bool recurse) {
- static ConstString g_kext_suffix = ConstString("kext");
- static ConstString g_dsym_suffix = ConstString("dSYM");
+ static ConstString g_kext_suffix = ConstString(".kext");
+ static ConstString g_dsym_suffix = ConstString(".dSYM");
static ConstString g_bundle_suffix = ConstString("Bundle");
ConstString file_spec_extension = file_spec.GetFileNameExtension();
@@ -633,7 +623,7 @@ bool PlatformDarwinKernel::KextHasdSYMSibling(
kext_bundle_filepath.GetPath() + "/Contents/MacOS/";
deep_bundle_str += executable_name.AsCString();
deep_bundle_str += ".dSYM";
- dsym_fspec.SetFile(deep_bundle_str, true);
+ dsym_fspec.SetFile(deep_bundle_str, true, FileSpec::Style::native);
if (llvm::sys::fs::is_directory(dsym_fspec.GetPath())) {
return true;
}
@@ -643,15 +633,15 @@ bool PlatformDarwinKernel::KextHasdSYMSibling(
std::string shallow_bundle_str = kext_bundle_filepath.GetPath() + "/";
shallow_bundle_str += executable_name.AsCString();
shallow_bundle_str += ".dSYM";
- dsym_fspec.SetFile(shallow_bundle_str, true);
+ dsym_fspec.SetFile(shallow_bundle_str, true, FileSpec::Style::native);
if (llvm::sys::fs::is_directory(dsym_fspec.GetPath())) {
return true;
}
return false;
}
-// Given a FileSpec of /dir/dir/mach.development.t7004
-// Return true if a dSYM exists next to it:
+// Given a FileSpec of /dir/dir/mach.development.t7004 Return true if a dSYM
+// exists next to it:
// /dir/dir/mach.development.t7004.dSYM
bool PlatformDarwinKernel::KernelHasdSYMSibling(const FileSpec &kernel_binary) {
FileSpec kernel_dsym = kernel_binary;
@@ -694,8 +684,8 @@ Status PlatformDarwinKernel::GetSharedModule(
}
}
- // Give the generic methods, including possibly calling into
- // DebugSymbols framework on macOS systems, a chance.
+ // Give the generic methods, including possibly calling into DebugSymbols
+ // framework on macOS systems, a chance.
error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
module_search_paths_ptr,
old_module_sp_ptr, did_create_ptr);
@@ -749,8 +739,8 @@ Status PlatformDarwinKernel::GetSharedModule(
}
}
- // Give the generic methods, including possibly calling into
- // DebugSymbols framework on macOS systems, a chance.
+ // Give the generic methods, including possibly calling into DebugSymbols
+ // framework on macOS systems, a chance.
error = PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
module_search_paths_ptr,
old_module_sp_ptr, did_create_ptr);
@@ -789,37 +779,53 @@ Status PlatformDarwinKernel::GetSharedModule(
return error;
}
+std::vector<lldb_private::FileSpec>
+PlatformDarwinKernel::SearchForExecutablesRecursively(const std::string &dir) {
+ std::vector<FileSpec> executables;
+ std::error_code EC;
+ for (llvm::sys::fs::recursive_directory_iterator it(dir.c_str(), EC),
+ end;
+ it != end && !EC; it.increment(EC)) {
+ auto status = it->status();
+ if (!status)
+ break;
+ if (llvm::sys::fs::is_regular_file(*status) &&
+ llvm::sys::fs::can_execute(it->path()))
+ executables.emplace_back(it->path(), false);
+ }
+ return executables;
+}
+
Status PlatformDarwinKernel::ExamineKextForMatchingUUID(
const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid,
const ArchSpec &arch, ModuleSP &exe_module_sp) {
- Status error;
- FileSpec exe_file = kext_bundle_path;
- Host::ResolveExecutableInBundle(exe_file);
- if (exe_file.Exists()) {
- ModuleSpec exe_spec(exe_file);
- exe_spec.GetUUID() = uuid;
- if (!uuid.IsValid()) {
- exe_spec.GetArchitecture() = arch;
- }
+ for (const auto &exe_file :
+ SearchForExecutablesRecursively(kext_bundle_path.GetPath())) {
+ if (exe_file.Exists()) {
+ ModuleSpec exe_spec(exe_file);
+ exe_spec.GetUUID() = uuid;
+ if (!uuid.IsValid()) {
+ exe_spec.GetArchitecture() = arch;
+ }
- // First try to create a ModuleSP with the file / arch and see if the UUID
- // matches.
- // If that fails (this exec file doesn't have the correct uuid), don't call
- // GetSharedModule
- // (which may call in to the DebugSymbols framework and therefore can be
- // slow.)
- ModuleSP module_sp(new Module(exe_spec));
- if (module_sp && module_sp->GetObjectFile() &&
- module_sp->MatchesModuleSpec(exe_spec)) {
- error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, NULL, NULL,
- NULL);
- if (exe_module_sp && exe_module_sp->GetObjectFile()) {
- return error;
+ // First try to create a ModuleSP with the file / arch and see if the UUID
+ // matches. If that fails (this exec file doesn't have the correct uuid),
+ // don't call GetSharedModule (which may call in to the DebugSymbols
+ // framework and therefore can be slow.)
+ ModuleSP module_sp(new Module(exe_spec));
+ if (module_sp && module_sp->GetObjectFile() &&
+ module_sp->MatchesModuleSpec(exe_spec)) {
+ Status error = ModuleList::GetSharedModule(exe_spec, exe_module_sp,
+ NULL, NULL, NULL);
+ if (exe_module_sp && exe_module_sp->GetObjectFile()) {
+ return error;
+ }
}
+ exe_module_sp.reset();
}
- exe_module_sp.reset();
}
- return error;
+
+ return {};
}
bool PlatformDarwinKernel::GetSupportedArchitectureAtIndex(uint32_t idx,
@@ -851,17 +857,13 @@ void PlatformDarwinKernel::CalculateTrapHandlerSymbolNames() {
#else // __APPLE__
-// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on
-// PlatformDarwinKernel for the plug-in name, we compile just the plug-in name
-// in
-// here to avoid issues. We are tracking an internal bug to resolve this issue
-// by
-// either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to
-// make
-// PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently
-// not
-// compiled on other platforms due to the use of the Mac-specific
-// source/Host/macosx/cfcpp utilities.
+// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies
+// on PlatformDarwinKernel for the plug-in name, we compile just the plug-in
+// name in here to avoid issues. We are tracking an internal bug to resolve
+// this issue by either not compiling in DynamicLoaderDarwinKernel for non-
+// apple builds, or to make PlatformDarwinKernel build on all systems.
+// PlatformDarwinKernel is currently not compiled on other platforms due to the
+// use of the Mac-specific source/Host/macosx/cfcpp utilities.
lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() {
static lldb_private::ConstString g_name("darwin-kernel");
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
index 9b3ec5e0d717..7f603cac2bec 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
@@ -127,6 +127,9 @@ protected:
const lldb_private::FileSpec &file_spec,
bool recurse);
+ static std::vector<lldb_private::FileSpec>
+ SearchForExecutablesRecursively(const std::string &dir);
+
static void AddKextToMap(PlatformDarwinKernel *thisp,
const lldb_private::FileSpec &file_spec);
@@ -201,6 +204,7 @@ public:
// source/Host/macosx/cfcpp utilities.
class PlatformDarwinKernel {
+public:
static lldb_private::ConstString GetPluginNameStatic();
};
diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
index 43f4d8bbf023..99f603b01f43 100644
--- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
@@ -91,9 +91,8 @@ PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__APPLE__)
- // Only accept "unknown" for vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for vendor if the host is Apple and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
@@ -109,9 +108,8 @@ PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) {
case llvm::Triple::MacOSX:
break;
#if defined(__APPLE__)
- // Only accept "vendor" for vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "vendor" for vendor if the host is Apple and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -175,7 +173,8 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
FileSpec fspec;
uint32_t versions[2];
if (objfile->GetSDKVersion(versions, sizeof(versions))) {
- if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, fspec)) {
+ fspec = HostInfo::GetShlibDir();
+ if (fspec) {
std::string path;
xcode_contents_path = fspec.GetPath();
size_t pos = xcode_contents_path.find("/Xcode.app/Contents/");
@@ -198,7 +197,7 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
// here
&output, // Get the output from the command and place it in this
// string
- 3); // Timeout in seconds to wait for shell program to finish
+ std::chrono::seconds(3));
if (status == 0 && !output.empty()) {
size_t first_non_newline = output.find_last_not_of("\r\n");
if (first_non_newline != std::string::npos)
@@ -219,13 +218,13 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
"SDKs/MacOSX%u.%u.sdk",
xcode_contents_path.c_str(), versions[0],
versions[1]);
- fspec.SetFile(sdk_path.GetString(), false);
+ fspec.SetFile(sdk_path.GetString(), false, FileSpec::Style::native);
if (fspec.Exists())
return ConstString(sdk_path.GetString());
}
if (!default_xcode_sdk.empty()) {
- fspec.SetFile(default_xcode_sdk, false);
+ fspec.SetFile(default_xcode_sdk, false, FileSpec::Style::native);
if (fspec.Exists())
return ConstString(default_xcode_sdk);
}
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
index 1eef643d3904..be4c829a981c 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
@@ -99,8 +99,8 @@ PlatformSP PlatformRemoteAppleTV::CreateInstance(bool force,
#if defined(__APPLE__)
// Only accept "unknown" for the vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
index 17ae67bc28de..6159511d4a18 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
@@ -94,8 +94,8 @@ PlatformSP PlatformRemoteAppleWatch::CreateInstance(bool force,
#if defined(__APPLE__)
// Only accept "unknown" for the vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
@@ -123,8 +123,8 @@ PlatformSP PlatformRemoteAppleWatch::CreateInstance(bool force,
#if defined(__APPLE__) && \
(defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
- // If lldb is running on a watch, this isn't a RemoteWatch environment; it's a
- // local system environment.
+ // If lldb is running on a watch, this isn't a RemoteWatch environment; it's
+ // a local system environment.
if (force == false) {
create = false;
}
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
index cb064aad6155..930d062fe41e 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
@@ -31,12 +31,10 @@ using namespace lldb_private;
PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo(
const lldb_private::FileSpec &sdk_dir)
- : directory(sdk_dir), build(), version_major(0), version_minor(0),
- version_update(0), user_cached(false) {
+ : directory(sdk_dir), build(), user_cached(false) {
llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
llvm::StringRef build_str;
- std::tie(version_major, version_minor, version_update, build_str) =
- ParseVersionBuildDir(dirname_str);
+ std::tie(version, build_str) = ParseVersionBuildDir(dirname_str);
build.SetString(build_str);
}
@@ -97,9 +95,9 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable(
return error;
exe_module_sp.reset();
}
- // No valid architecture was specified or the exact ARM slice wasn't
- // found so ask the platform for the architectures that we should be
- // using (in the correct order) and see if we can find a match that way
+ // No valid architecture was specified or the exact ARM slice wasn't found
+ // so ask the platform for the architectures that we should be using (in
+ // the correct order) and see if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
@@ -183,8 +181,8 @@ bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
&builtin_sdk_directory_infos);
// Only add SDK directories that have symbols in them, some SDKs only
- // contain
- // developer disk images and no symbols, so they aren't useful to us.
+ // contain developer disk images and no symbols, so they aren't useful to
+ // us.
FileSpec sdk_symbols_symlink_fspec;
for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
sdk_symbols_symlink_fspec = sdk_directory_info.directory;
@@ -244,8 +242,8 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {
if (UpdateSDKDirectoryInfosIfNeeded()) {
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
- // Check to see if the user specified a build string. If they did, then
- // be sure to match it.
+ // Check to see if the user specified a build string. If they did, then be
+ // sure to match it.
std::vector<bool> check_sdk_info(num_sdk_infos, true);
ConstString build(m_sdk_build);
if (build) {
@@ -253,26 +251,25 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {
check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
}
- // If we are connected we can find the version of the OS the platform
- // us running on and select the right SDK
- uint32_t major, minor, update;
- if (GetOSVersion(major, minor, update)) {
+ // If we are connected we can find the version of the OS the platform us
+ // running on and select the right SDK
+ llvm::VersionTuple version = GetOSVersion();
+ if (!version.empty()) {
if (UpdateSDKDirectoryInfosIfNeeded()) {
// First try for an exact match of major, minor and update
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
- if (m_sdk_directory_infos[i].version_major == major &&
- m_sdk_directory_infos[i].version_minor == minor &&
- m_sdk_directory_infos[i].version_update == update) {
+ if (m_sdk_directory_infos[i].version == version)
return &m_sdk_directory_infos[i];
- }
}
}
// First try for an exact match of major and minor
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
- if (m_sdk_directory_infos[i].version_major == major &&
- m_sdk_directory_infos[i].version_minor == minor) {
+ if (m_sdk_directory_infos[i].version.getMajor() ==
+ version.getMajor() &&
+ m_sdk_directory_infos[i].version.getMinor() ==
+ version.getMinor()) {
return &m_sdk_directory_infos[i];
}
}
@@ -280,7 +277,8 @@ PlatformRemoteDarwinDevice::GetSDKDirectoryForCurrentOSVersion() {
// Lastly try to match of major version only..
for (i = 0; i < num_sdk_infos; ++i) {
if (check_sdk_info[i]) {
- if (m_sdk_directory_infos[i].version_major == major) {
+ if (m_sdk_directory_infos[i].version.getMajor() ==
+ version.getMajor()) {
return &m_sdk_directory_infos[i];
}
}
@@ -300,25 +298,13 @@ const PlatformRemoteDarwinDevice::SDKDirectoryInfo *
PlatformRemoteDarwinDevice::GetSDKDirectoryForLatestOSVersion() {
const PlatformRemoteDarwinDevice::SDKDirectoryInfo *result = NULL;
if (UpdateSDKDirectoryInfosIfNeeded()) {
- const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
- // First try for an exact match of major, minor and update
- for (uint32_t i = 0; i < num_sdk_infos; ++i) {
- const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
- if (sdk_dir_info.version_major != UINT32_MAX) {
- if (result == NULL ||
- sdk_dir_info.version_major > result->version_major) {
- result = &sdk_dir_info;
- } else if (sdk_dir_info.version_major == result->version_major) {
- if (sdk_dir_info.version_minor > result->version_minor) {
- result = &sdk_dir_info;
- } else if (sdk_dir_info.version_minor == result->version_minor) {
- if (sdk_dir_info.version_update > result->version_update) {
- result = &sdk_dir_info;
- }
- }
- }
- }
- }
+ auto max = std::max_element(
+ m_sdk_directory_infos.begin(), m_sdk_directory_infos.end(),
+ [](const SDKDirectoryInfo &a, const SDKDirectoryInfo &b) {
+ return a.version < b.version;
+ });
+ if (max != m_sdk_directory_infos.end())
+ result = &*max;
}
return result;
}
@@ -366,8 +352,8 @@ const char *PlatformRemoteDarwinDevice::GetDeviceSupportDirectoryForOSVersion()
}
}
// We should have put a single NULL character into
- // m_device_support_directory_for_os_version
- // or it should have a valid path if the code gets here
+ // m_device_support_directory_for_os_version or it should have a valid path
+ // if the code gets here
assert(m_device_support_directory_for_os_version.empty() == false);
if (m_device_support_directory_for_os_version[0])
return m_device_support_directory_for_os_version.c_str();
@@ -409,7 +395,7 @@ bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
- local_file.SetFile(sdkroot_path, false);
+ local_file.SetFile(sdkroot_path, false, FileSpec::Style::native);
if (paths_to_try[i][0] != '\0')
local_file.AppendPathComponent(paths_to_try[i]);
local_file.AppendPathComponent(platform_file_path);
@@ -442,7 +428,7 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
platform_file_path);
- local_file.SetFile(resolved_path, true);
+ local_file.SetFile(resolved_path, true, FileSpec::Style::native);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s",
@@ -454,7 +440,7 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
os_version_dir, platform_file_path);
- local_file.SetFile(resolved_path, true);
+ local_file.SetFile(resolved_path, true, FileSpec::Style::native);
if (local_file.Exists()) {
if (log) {
log->Printf(
@@ -466,7 +452,7 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
os_version_dir, platform_file_path);
- local_file.SetFile(resolved_path, true);
+ local_file.SetFile(resolved_path, true, FileSpec::Style::native);
if (local_file.Exists()) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
@@ -492,10 +478,9 @@ Status PlatformRemoteDarwinDevice::GetSharedModule(
const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) {
- // For iOS, the SDK files are all cached locally on the host
- // system. So first we ask for the file in the cached SDK,
- // then we attempt to get a shared module for the right architecture
- // with the right UUID.
+ // For iOS, the SDK files are all cached locally on the host system. So first
+ // we ask for the file in the cached SDK, then we attempt to get a shared
+ // module for the right architecture with the right UUID.
const FileSpec &platform_file = module_spec.GetFileSpec();
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
@@ -510,8 +495,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule(
const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
// If we are connected we migth be able to correctly deduce the SDK
- // directory
- // using the OS build.
+ // directory using the OS build.
const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
if (connected_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
@@ -528,8 +512,8 @@ Status PlatformRemoteDarwinDevice::GetSharedModule(
}
}
- // Try the last SDK index if it is set as most files from an SDK
- // will tend to be valid in that same SDK.
+ // Try the last SDK index if it is set as most files from an SDK will tend
+ // to be valid in that same SDK.
if (m_last_module_sdk_idx < num_sdk_infos) {
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
m_sdk_directory_infos[m_last_module_sdk_idx].directory);
@@ -544,9 +528,9 @@ Status PlatformRemoteDarwinDevice::GetSharedModule(
}
}
- // First try for an exact match of major, minor and update:
- // If a particalar SDK version was specified via --version or --build, look
- // for a match on disk.
+ // First try for an exact match of major, minor and update: If a particalar
+ // SDK version was specified via --version or --build, look for a match on
+ // disk.
const SDKDirectoryInfo *current_sdk_info =
GetSDKDirectoryForCurrentOSVersion();
const uint32_t current_sdk_idx =
@@ -570,8 +554,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule(
// Second try all SDKs that were found.
for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
if (m_last_module_sdk_idx == sdk_idx) {
- // Skip the last module SDK index if we already searched
- // it above
+ // Skip the last module SDK index if we already searched it above
continue;
}
LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
@@ -582,8 +565,8 @@ Status PlatformRemoteDarwinDevice::GetSharedModule(
error = ResolveExecutable(platform_module_spec, module_sp, NULL);
if (module_sp) {
- // Remember the index of the last SDK that we found a file
- // in in case the wrong SDK was selected.
+ // Remember the index of the last SDK that we found a file in in case
+ // the wrong SDK was selected.
m_last_module_sdk_idx = sdk_idx;
error.Clear();
return error;
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
index f159e8575d76..8ddfd51600fd 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
@@ -60,9 +60,7 @@ protected:
SDKDirectoryInfo(const lldb_private::FileSpec &sdk_dir_spec);
lldb_private::FileSpec directory;
lldb_private::ConstString build;
- uint32_t version_major;
- uint32_t version_minor;
- uint32_t version_update;
+ llvm::VersionTuple version;
bool user_cached;
};
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
index 5bff792525bc..150bfdbfc118 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
@@ -89,8 +89,8 @@ PlatformSP PlatformRemoteiOS::CreateInstance(bool force, const ArchSpec *arch) {
#if defined(__APPLE__)
// Only accept "unknown" for the vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
index ee1f90311e7e..26feec282322 100644
--- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
@@ -91,9 +91,9 @@ PlatformSP PlatformiOSSimulator::CreateInstance(bool force,
break;
#if defined(__APPLE__)
- // Only accept "unknown" for the vendor if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the vendor if the host is Apple and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownArch:
create = !arch->TripleVendorWasSpecified();
break;
@@ -112,9 +112,9 @@ PlatformSP PlatformiOSSimulator::CreateInstance(bool force,
break;
#if defined(__APPLE__)
- // Only accept "unknown" for the OS if the host is Apple and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is Apple and it
+ // "unknown" wasn't specified (it was just returned because it was NOT
+ // specified)
case llvm::Triple::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -205,9 +205,9 @@ Status PlatformiOSSimulator::ResolveExecutable(
return error;
exe_module_sp.reset();
}
- // No valid architecture was specified or the exact ARM slice wasn't
- // found so ask the platform for the architectures that we should be
- // using (in the correct order) and see if we can find a match that way
+ // No valid architecture was specified or the exact ARM slice wasn't found
+ // so ask the platform for the architectures that we should be using (in
+ // the correct order) and see if we can find a match that way
StreamString arch_names;
ArchSpec platform_arch;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
@@ -298,8 +298,8 @@ const char *PlatformiOSSimulator::GetSDKDirectoryAsCString() {
m_sdk_directory.assign(1, '\0');
}
- // We should have put a single NULL character into m_sdk_directory
- // or it should have a valid path if the code gets here
+ // We should have put a single NULL character into m_sdk_directory or it
+ // should have a valid path if the code gets here
assert(m_sdk_directory.empty() == false);
if (m_sdk_directory[0])
return m_sdk_directory.c_str();
@@ -320,12 +320,12 @@ Status PlatformiOSSimulator::GetSymbolFile(const FileSpec &platform_file,
platform_file_path);
// First try in the SDK and see if the file is in there
- local_file.SetFile(resolved_path, true);
+ local_file.SetFile(resolved_path, true, FileSpec::Style::native);
if (local_file.Exists())
return error;
// Else fall back to the actual path itself
- local_file.SetFile(platform_file_path, true);
+ local_file.SetFile(platform_file_path, true, FileSpec::Style::native);
if (local_file.Exists())
return error;
}
@@ -342,10 +342,9 @@ Status PlatformiOSSimulator::GetSharedModule(
const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
bool *did_create_ptr) {
- // For iOS, the SDK files are all cached locally on the host
- // system. So first we ask for the file in the cached SDK,
- // then we attempt to get a shared module for the right architecture
- // with the right UUID.
+ // For iOS, the SDK files are all cached locally on the host system. So first
+ // we ask for the file in the cached SDK, then we attempt to get a shared
+ // module for the right architecture with the right UUID.
Status error;
ModuleSpec platform_module_spec(module_spec);
const FileSpec &platform_file = module_spec.GetFileSpec();
@@ -409,14 +408,14 @@ bool PlatformiOSSimulator::GetSupportedArchitectureAtIndex(uint32_t idx,
if (arch.IsValid()) {
if (idx == 2)
arch.GetTriple().setOS(llvm::Triple::IOS);
- // 32/64: return "i386-apple-ios" for architecture 2
- // 32/64: return "i386-apple-macosx" for architecture 3
+ // 32/64: return "i386-apple-ios" for architecture 2 32/64: return
+ // "i386-apple-macosx" for architecture 3
return true;
}
}
} else if (idx == 1) {
- // This macosx platform supports only 32 bit, so return the *-apple-macosx
- // version
+ // This macosx platform supports only 32 bit, so return the *-apple-
+ // macosx version
arch = platform_arch;
return true;
}
diff --git a/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt b/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt
new file mode 100644
index 000000000000..946ff0a64c26
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/objcxx/CMakeLists.txt
@@ -0,0 +1,17 @@
+remove_module_flags()
+include_directories(.)
+
+add_lldb_library(lldbPluginPlatformMacOSXObjCXX
+ PlatformiOSSimulatorCoreSimulatorSupport.mm
+
+ LINK_LIBS
+ lldbCore
+ lldbSymbol
+ lldbTarget
+ lldbUtility
+ ${EXTRA_LIBS}
+
+ LINK_COMPONENTS
+ Object
+ Support
+ )
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
index 31e11a60e419..083e2d6c5687 100644
--- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h
+++ b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
@@ -24,8 +24,8 @@
typedef void *id;
#endif
// Project includes
-#include "lldb/Interpreter/Args.h"
#include "lldb/Target/ProcessLaunchInfo.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
index 7bd37683d2fd..4516a66ee8ca 100644
--- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm
+++ b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
@@ -478,26 +478,17 @@ CoreSimulatorSupport::Device::Spawn(ProcessLaunchInfo &launch_info) {
[options setObject:args_array forKey:kSimDeviceSpawnArguments];
}
- if (launch_info.GetEnvironmentEntries().GetArgumentCount()) {
- const Args &envs(launch_info.GetEnvironmentEntries());
- NSMutableDictionary *env_dict = [[NSMutableDictionary alloc] init];
- for (size_t idx = 0; idx < envs.GetArgumentCount(); idx++) {
- llvm::StringRef arg_sr(envs.GetArgumentAtIndex(idx));
- auto first_eq = arg_sr.find('=');
- if (first_eq == llvm::StringRef::npos)
- continue;
- llvm::StringRef key = arg_sr.substr(0, first_eq);
- llvm::StringRef value = arg_sr.substr(first_eq + 1);
-
- NSString *key_ns = [NSString stringWithUTF8String:key.str().c_str()];
- NSString *value_ns = [NSString stringWithUTF8String:value.str().c_str()];
-
- [env_dict setValue:value_ns forKey:key_ns];
- }
+ NSMutableDictionary *env_dict = [[NSMutableDictionary alloc] init];
+
+ for (const auto &KV : launch_info.GetEnvironment()) {
+ NSString *key_ns = [NSString stringWithUTF8String:KV.first().str().c_str()];
+ NSString *value_ns = [NSString stringWithUTF8String:KV.second.c_str()];
- [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment];
+ [env_dict setValue:value_ns forKey:key_ns];
}
+ [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment];
+
Status error;
File stdin_file;
File stdout_file;
diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
index 38bdf60c1ced..3aa8ecb4c228 100644
--- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
+++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -30,8 +30,8 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
-// Define these constants from NetBSD mman.h for use when targeting
-// remote netbsd systems even when host has different values.
+// Define these constants from NetBSD mman.h for use when targeting remote
+// netbsd systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000
@@ -45,19 +45,9 @@ static uint32_t g_initialize_count = 0;
PlatformSP PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log) {
- const char *arch_name;
- if (arch && arch->GetArchitectureName())
- arch_name = arch->GetArchitectureName();
- else
- arch_name = "<null>";
-
- const char *triple_cstr =
- arch ? arch->GetTriple().getTriple().c_str() : "<null>";
-
- log->Printf("PlatformNetBSD::%s(force=%s, arch={%s,%s})", __FUNCTION__,
- force ? "true" : "false", arch_name, triple_cstr);
- }
+ LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
+ arch ? arch->GetArchitectureName() : "<null>",
+ arch ? arch->GetTriple().getTriple() : "<null>");
bool create = force;
if (create == false && arch && arch->IsValid()) {
@@ -72,18 +62,10 @@ PlatformSP PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch) {
}
}
+ LLDB_LOG(log, "create = {0}", create);
if (create) {
- if (log)
- log->Printf("PlatformNetBSD::%s() creating remote-netbsd platform",
- __FUNCTION__);
return PlatformSP(new PlatformNetBSD(false));
}
-
- if (log)
- log->Printf(
- "PlatformNetBSD::%s() aborting creation of remote-netbsd platform",
- __FUNCTION__);
-
return PlatformSP();
}
@@ -152,7 +134,8 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
- // If the default host architecture is 64-bit, look for a 32-bit variant
+ // If the default host architecture is 64-bit, look for a 32-bit
+ // variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
@@ -178,13 +161,10 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
- // vendor by
- // calling triple.SetVendorName("unknown") so that it is a "unspecified
- // unknown".
- // This means when someone calls triple.GetVendorName() it will return an
- // empty string
- // which indicates that the vendor can be set when two architectures are
- // merged
+ // vendor by calling triple.SetVendorName("unknown") so that it is a
+ // "unspecified unknown". This means when someone calls
+ // triple.GetVendorName() it will return an empty string which indicates
+ // that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
@@ -258,19 +238,15 @@ bool PlatformNetBSD::CanDebugProcess() {
}
// For local debugging, NetBSD will override the debug logic to use llgs-launch
-// rather than
-// lldb-launch, llgs-attach. This differs from current lldb-launch,
-// debugserver-attach
-// approach on MacOSX.
-lldb::ProcessSP PlatformNetBSD::DebugProcess(
- ProcessLaunchInfo &launch_info, Debugger &debugger,
- Target *target, // Can be NULL, if NULL create a new
- // target, else use existing one
- Status &error) {
+// rather than lldb-launch, llgs-attach. This differs from current lldb-
+// launch, debugserver-attach approach on MacOSX.
+lldb::ProcessSP
+PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
+ Target *target, // Can be NULL, if NULL create a new
+ // target, else use existing one
+ Status &error) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf("PlatformNetBSD::%s entered (target %p)", __FUNCTION__,
- static_cast<void *>(target));
+ LLDB_LOG(log, "target {0}", target);
// If we're a remote host, use standard behavior from parent class.
if (!IsHost())
@@ -287,67 +263,48 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess(
launch_info.GetFlags().Set(eLaunchFlagDebug);
// We always launch the process we are going to debug in a separate process
- // group, since then we can handle ^C interrupts ourselves w/o having to worry
- // about the target getting them as well.
+ // group, since then we can handle ^C interrupts ourselves w/o having to
+ // worry about the target getting them as well.
launch_info.SetLaunchInSeparateProcessGroup(true);
// Ensure we have a target.
if (target == nullptr) {
- if (log)
- log->Printf("PlatformNetBSD::%s creating new target", __FUNCTION__);
-
+ LLDB_LOG(log, "creating new target");
TargetSP new_target_sp;
error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
nullptr, new_target_sp);
if (error.Fail()) {
- if (log)
- log->Printf("PlatformNetBSD::%s failed to create new target: %s",
- __FUNCTION__, error.AsCString());
+ LLDB_LOG(log, "failed to create new target: {0}", error);
return process_sp;
}
target = new_target_sp.get();
if (!target) {
error.SetErrorString("CreateTarget() returned nullptr");
- if (log)
- log->Printf("PlatformNetBSD::%s failed: %s", __FUNCTION__,
- error.AsCString());
+ LLDB_LOG(log, "error: {0}", error);
return process_sp;
}
- } else {
- if (log)
- log->Printf("PlatformNetBSD::%s using provided target", __FUNCTION__);
}
// Mark target as currently selected target.
debugger.GetTargetList().SetSelectedTarget(target);
// Now create the gdb-remote process.
- if (log)
- log->Printf(
- "PlatformNetBSD::%s having target create process with gdb-remote plugin",
- __FUNCTION__);
+ LLDB_LOG(log, "having target create process with gdb-remote plugin");
process_sp = target->CreateProcess(
launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr);
if (!process_sp) {
error.SetErrorString("CreateProcess() failed for gdb-remote process");
- if (log)
- log->Printf("PlatformNetBSD::%s failed: %s", __FUNCTION__,
- error.AsCString());
+ LLDB_LOG(log, "error: {0}", error);
return process_sp;
- } else {
- if (log)
- log->Printf("PlatformNetBSD::%s successfully created process",
- __FUNCTION__);
}
+ LLDB_LOG(log, "successfully created process");
// Adjust launch for a hijacker.
ListenerSP listener_sp;
if (!launch_info.GetHijackListener()) {
- if (log)
- log->Printf("PlatformNetBSD::%s setting up hijacker", __FUNCTION__);
-
+ LLDB_LOG(log, "setting up hijacker");
listener_sp =
Listener::MakeListener("lldb.PlatformNetBSD.DebugProcess.hijack");
launch_info.SetHijackListener(listener_sp);
@@ -356,16 +313,13 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess(
// Log file actions.
if (log) {
- log->Printf(
- "PlatformNetBSD::%s launching process with the following file actions:",
- __FUNCTION__);
-
+ LLDB_LOG(log, "launching process with the following file actions:");
StreamString stream;
size_t i = 0;
const FileAction *file_action;
while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) {
file_action->Dump(stream);
- log->PutCString(stream.GetData());
+ LLDB_LOG(log, "{0}", stream.GetData());
stream.Clear();
}
}
@@ -378,16 +332,7 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess(
const StateType state = process_sp->WaitForProcessToStop(
llvm::None, NULL, false, listener_sp);
- if (state == eStateStopped) {
- if (log)
- log->Printf("PlatformNetBSD::%s pid %" PRIu64 " state %s\n",
- __FUNCTION__, process_sp->GetID(), StateAsCString(state));
- } else {
- if (log)
- log->Printf("PlatformNetBSD::%s pid %" PRIu64
- " state is not stopped - %s\n",
- __FUNCTION__, process_sp->GetID(), StateAsCString(state));
- }
+ LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state);
}
// Hook up process PTY if we have one (which we should for local debugging
@@ -395,20 +340,11 @@ lldb::ProcessSP PlatformNetBSD::DebugProcess(
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
- if (log)
- log->Printf("PlatformNetBSD::%s pid %" PRIu64
- " hooked up STDIO pty to process",
- __FUNCTION__, process_sp->GetID());
- } else {
- if (log)
- log->Printf("PlatformNetBSD::%s pid %" PRIu64
- " not using process STDIO pty",
- __FUNCTION__, process_sp->GetID());
- }
+ LLDB_LOG(log, "hooked up STDIO pty to process");
+ } else
+ LLDB_LOG(log, "not using process STDIO pty");
} else {
- if (log)
- log->Printf("PlatformNetBSD::%s process launch failed: %s", __FUNCTION__,
- error.AsCString());
+ LLDB_LOG(log, "process launch failed: {0}", error);
// FIXME figure out appropriate cleanup here. Do we delete the target? Do
// we delete the process? Does our caller do that?
}
diff --git a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
index 050639aba7cc..10ca8fbfbdd7 100644
--- a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
+++ b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
@@ -30,8 +30,8 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
-// Define these constants from OpenBSD mman.h for use when targeting
-// remote openbsd systems even when host has different values.
+// Define these constants from OpenBSD mman.h for use when targeting remote
+// openbsd systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000
@@ -58,9 +58,8 @@ PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) {
break;
#if defined(__OpenBSD__)
- // Only accept "unknown" for the OS if the host is BSD and
- // it "unknown" wasn't specified (it was just returned because it
- // was NOT specified)
+ // Only accept "unknown" for the OS if the host is BSD and it "unknown"
+ // wasn't specified (it was just returned because it was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
@@ -167,13 +166,10 @@ bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
- // vendor by
- // calling triple.SetVendorName("unknown") so that it is a "unspecified
- // unknown".
- // This means when someone calls triple.GetVendorName() it will return an
- // empty string
- // which indicates that the vendor can be set when two architectures are
- // merged
+ // vendor by calling triple.SetVendorName("unknown") so that it is a
+ // "unspecified unknown". This means when someone calls
+ // triple.GetVendorName() it will return an empty string which indicates
+ // that the vendor can be set when two architectures are merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index d45a54ee2499..5e7ffe71918e 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -18,17 +18,22 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/DiagnosticManager.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileCache.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
@@ -97,17 +102,14 @@ lldb_private::Status PlatformPOSIX::RunShellCommand(
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t
- timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
+ const Timeout<std::micro> &timeout) {
if (IsHost())
return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr,
- command_output, timeout_sec);
+ command_output, timeout);
else {
if (m_remote_platform_sp)
- return m_remote_platform_sp->RunShellCommand(command, working_dir,
- status_ptr, signo_ptr,
- command_output, timeout_sec);
+ return m_remote_platform_sp->RunShellCommand(
+ command, working_dir, status_ptr, signo_ptr, command_output, timeout);
else
return Status("unable to run a remote command without a platform");
}
@@ -124,11 +126,12 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
ModuleSpec resolved_module_spec(module_spec);
if (IsHost()) {
- // If we have "ls" as the exe_file, resolve the executable location based on
- // the current path variables
+ // If we have "ls" as the exe_file, resolve the executable location based
+ // on the current path variables
if (!resolved_module_spec.GetFileSpec().Exists()) {
resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
- resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true,
+ FileSpec::Style::native);
}
if (!resolved_module_spec.GetFileSpec().Exists())
@@ -210,9 +213,9 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
resolved_module_spec.GetArchitecture().GetArchitectureName());
}
} else {
- // No valid architecture was specified, ask the platform for
- // the architectures that we should be using (in the correct order)
- // and see if we can find a match that way
+ // No valid architecture was specified, ask the platform for the
+ // architectures that we should be using (in the correct order) and see
+ // if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
@@ -367,7 +370,8 @@ static uint32_t chown_file(Platform *platform, const char *path,
command.Printf(":%d", gid);
command.Printf("%s", path);
int status;
- platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10);
+ platform->RunShellCommand(command.GetData(), NULL, &status, NULL, NULL,
+ std::chrono::seconds(10));
return status;
}
@@ -391,7 +395,8 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
StreamString command;
command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(command.GetData(), NULL, &status, NULL, NULL, 10);
+ RunShellCommand(command.GetData(), NULL, &status, NULL, NULL,
+ std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
if (uid == UINT32_MAX && gid == UINT32_MAX)
@@ -421,7 +426,8 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
if (log)
log->Printf("[PutFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60);
+ Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL,
+ std::chrono::minutes(1));
if (retcode == 0) {
// Don't chown a local file for a remote system
// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
@@ -495,7 +501,8 @@ lldb_private::Status PlatformPOSIX::GetFile(
StreamString cp_command;
cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL, 10);
+ RunShellCommand(cp_command.GetData(), NULL, &status, NULL, NULL,
+ std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
return Status();
@@ -516,11 +523,12 @@ lldb_private::Status PlatformPOSIX::GetFile(
if (log)
log->Printf("[GetFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL, 60);
+ Host::RunShellCommand(command.GetData(), NULL, &retcode, NULL, NULL,
+ std::chrono::minutes(1));
if (retcode == 0)
return Status();
- // If we are here, rsync has failed - let's try the slow way before giving
- // up
+ // If we are here, rsync has failed - let's try the slow way before
+ // giving up
}
// open src and dst
// read/write, read/write, read/write, ...
@@ -645,9 +653,10 @@ bool PlatformPOSIX::SetRemoteWorkingDirectory(const FileSpec &working_dir) {
}
bool PlatformPOSIX::GetRemoteOSVersion() {
- if (m_remote_platform_sp)
- return m_remote_platform_sp->GetOSVersion(
- m_major_os_version, m_minor_os_version, m_update_os_version);
+ if (m_remote_platform_sp) {
+ m_os_version = m_remote_platform_sp->GetOSVersion();
+ return !m_os_version.empty();
+ }
return false;
}
@@ -658,13 +667,13 @@ bool PlatformPOSIX::GetRemoteOSBuildString(std::string &s) {
return false;
}
-size_t PlatformPOSIX::GetEnvironment(StringList &env) {
+Environment PlatformPOSIX::GetEnvironment() {
if (IsRemote()) {
if (m_remote_platform_sp)
- return m_remote_platform_sp->GetEnvironment(env);
- return 0;
+ return m_remote_platform_sp->GetEnvironment();
+ return Environment();
}
- return Host::GetEnvironment(env);
+ return Host::GetEnvironment();
}
bool PlatformPOSIX::GetRemoteOSKernelDescription(std::string &s) {
@@ -861,12 +870,12 @@ PlatformPOSIX::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
if (IsHost()) {
// We are going to hand this process off to debugserver which will be in
- // charge of setting the exit status.
- // We still need to reap it from lldb but if we let the monitor thread also
- // set the exit status, we set up a
- // race between debugserver & us for who will find out about the debugged
- // process's death.
- launch_info.GetFlags().Set(eLaunchFlagDontSetExitStatus);
+ // charge of setting the exit status. However, we still need to reap it
+ // from lldb. So, make sure we use a exit callback which does not set exit
+ // status.
+ const bool monitor_signals = false;
+ launch_info.SetMonitorProcessCallback(
+ &ProcessLaunchInfo::NoOpMonitorCallback, monitor_signals);
process_sp = Platform::DebugProcess(launch_info, debugger, target, error);
} else {
if (m_remote_platform_sp)
@@ -923,64 +932,380 @@ Status PlatformPOSIX::EvaluateLibdlExpression(
return Status();
}
+std::unique_ptr<UtilityFunction>
+PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
+ Status &error) {
+ // Remember to prepend this with the prefix from
+ // GetLibdlFunctionDeclarations. The returned values are all in
+ // __lldb_dlopen_result for consistency. The wrapper returns a void * but
+ // doesn't use it because UtilityFunctions don't work with void returns at
+ // present.
+ static const char *dlopen_wrapper_code = R"(
+ struct __lldb_dlopen_result {
+ void *image_ptr;
+ const char *error_str;
+ };
+
+ extern void *memcpy(void *, const void *, size_t size);
+ extern size_t strlen(const char *);
+
+
+ void * __lldb_dlopen_wrapper (const char *name,
+ const char *path_strings,
+ char *buffer,
+ __lldb_dlopen_result *result_ptr)
+ {
+ // This is the case where the name is the full path:
+ if (!path_strings) {
+ result_ptr->image_ptr = dlopen(name, 2);
+ if (result_ptr->image_ptr)
+ result_ptr->error_str = nullptr;
+ return nullptr;
+ }
+
+ // This is the case where we have a list of paths:
+ size_t name_len = strlen(name);
+ while (path_strings && path_strings[0] != '\0') {
+ size_t path_len = strlen(path_strings);
+ memcpy((void *) buffer, (void *) path_strings, path_len);
+ buffer[path_len] = '/';
+ char *target_ptr = buffer+path_len+1;
+ memcpy((void *) target_ptr, (void *) name, name_len + 1);
+ result_ptr->image_ptr = dlopen(buffer, 2);
+ if (result_ptr->image_ptr) {
+ result_ptr->error_str = nullptr;
+ break;
+ }
+ result_ptr->error_str = dlerror();
+ path_strings = path_strings + path_len + 1;
+ }
+ return nullptr;
+ }
+ )";
+
+ static const char *dlopen_wrapper_name = "__lldb_dlopen_wrapper";
+ Process *process = exe_ctx.GetProcessSP().get();
+ // Insert the dlopen shim defines into our generic expression:
+ std::string expr(GetLibdlFunctionDeclarations(process));
+ expr.append(dlopen_wrapper_code);
+ Status utility_error;
+ DiagnosticManager diagnostics;
+
+ std::unique_ptr<UtilityFunction> dlopen_utility_func_up(process
+ ->GetTarget().GetUtilityFunctionForLanguage(expr.c_str(),
+ eLanguageTypeObjC,
+ dlopen_wrapper_name,
+ utility_error));
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not make utility"
+ "function: %s", utility_error.AsCString());
+ return nullptr;
+ }
+ if (!dlopen_utility_func_up->Install(diagnostics, exe_ctx)) {
+ error.SetErrorStringWithFormat("dlopen error: could not install utility"
+ "function: %s",
+ diagnostics.GetString().c_str());
+ return nullptr;
+ }
+
+ Value value;
+ ValueList arguments;
+ FunctionCaller *do_dlopen_function = nullptr;
+
+ // Fetch the clang types we will need:
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ CompilerType clang_void_pointer_type
+ = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_char_pointer_type
+ = ast->GetBasicType(eBasicTypeChar).GetPointerType();
+
+ // We are passing four arguments, the basename, the list of places to look,
+ // a buffer big enough for all the path + name combos, and
+ // a pointer to the storage we've made for the result:
+ value.SetValueType(Value::eValueTypeScalar);
+ value.SetCompilerType(clang_void_pointer_type);
+ arguments.PushValue(value);
+ value.SetCompilerType(clang_char_pointer_type);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+ arguments.PushValue(value);
+
+ do_dlopen_function = dlopen_utility_func_up->MakeFunctionCaller(
+ clang_void_pointer_type, arguments, exe_ctx.GetThreadSP(), utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not make function"
+ "caller: %s", utility_error.AsCString());
+ return nullptr;
+ }
+
+ do_dlopen_function = dlopen_utility_func_up->GetFunctionCaller();
+ if (!do_dlopen_function) {
+ error.SetErrorString("dlopen error: could not get function caller.");
+ return nullptr;
+ }
+
+ // We made a good utility function, so cache it in the process:
+ return dlopen_utility_func_up;
+}
+
uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
const lldb_private::FileSpec &remote_file,
- lldb_private::Status &error) {
- char path[PATH_MAX];
- remote_file.GetPath(path, sizeof(path));
-
- StreamString expr;
- expr.Printf(R"(
- struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result;
- the_result.image_ptr = dlopen ("%s", 2);
- if (the_result.image_ptr == (void *) 0x0)
- {
- the_result.error_str = dlerror();
- }
- else
- {
- the_result.error_str = (const char *) 0x0;
- }
- the_result;
- )",
- path);
- llvm::StringRef prefix = GetLibdlFunctionDeclarations(process);
- lldb::ValueObjectSP result_valobj_sp;
- error = EvaluateLibdlExpression(process, expr.GetData(), prefix,
- result_valobj_sp);
- if (error.Fail())
+ const std::vector<std::string> *paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_image) {
+ if (loaded_image)
+ loaded_image->Clear();
+
+ std::string path;
+ path = remote_file.GetPath();
+
+ ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
+ if (!thread_sp) {
+ error.SetErrorString("dlopen error: no thread available to call dlopen.");
return LLDB_INVALID_IMAGE_TOKEN;
-
- error = result_valobj_sp->GetError();
- if (error.Fail())
+ }
+
+ DiagnosticManager diagnostics;
+
+ ExecutionContext exe_ctx;
+ thread_sp->CalculateExecutionContext(exe_ctx);
+
+ Status utility_error;
+ UtilityFunction *dlopen_utility_func;
+ ValueList arguments;
+ FunctionCaller *do_dlopen_function = nullptr;
+
+ // The UtilityFunction is held in the Process. Platforms don't track the
+ // lifespan of the Targets that use them, we can't put this in the Platform.
+ dlopen_utility_func = process->GetLoadImageUtilityFunction(
+ this, [&]() -> std::unique_ptr<UtilityFunction> {
+ return MakeLoadImageUtilityFunction(exe_ctx, error);
+ });
+ // If we couldn't make it, the error will be in error, so we can exit here.
+ if (!dlopen_utility_func)
return LLDB_INVALID_IMAGE_TOKEN;
-
- Scalar scalar;
- ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
- if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar)) {
- error.SetErrorStringWithFormat("unable to load '%s'", path);
+
+ do_dlopen_function = dlopen_utility_func->GetFunctionCaller();
+ if (!do_dlopen_function) {
+ error.SetErrorString("dlopen error: could not get function caller.");
return LLDB_INVALID_IMAGE_TOKEN;
}
-
- addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
- if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
- return process->AddImageToken(image_ptr);
-
- if (image_ptr == 0) {
- ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
- if (error_str_sp) {
- DataBufferSP buffer_sp(new DataBufferHeap(10240, 0));
- size_t num_chars =
- error_str_sp->ReadPointedString(buffer_sp, error, 10240).first;
- if (error.Success() && num_chars > 0)
- error.SetErrorStringWithFormat("dlopen error: %s",
- buffer_sp->GetBytes());
- else
- error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
+ arguments = do_dlopen_function->GetArgumentValues();
+
+ // Now insert the path we are searching for and the result structure into the
+ // target.
+ uint32_t permissions = ePermissionsReadable|ePermissionsWritable;
+ size_t path_len = path.size() + 1;
+ lldb::addr_t path_addr = process->AllocateMemory(path_len,
+ permissions,
+ utility_error);
+ if (path_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for path: %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we deallocate the input string memory:
+ CleanUp path_cleanup([process, path_addr] {
+ process->DeallocateMemory(path_addr);
+ });
+
+ process->WriteMemory(path_addr, path.c_str(), path_len, utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not write path string:"
+ " %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make space for our return structure. It is two pointers big: the token
+ // and the error string.
+ const uint32_t addr_size = process->GetAddressByteSize();
+ lldb::addr_t return_addr = process->CallocateMemory(2*addr_size,
+ permissions,
+ utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for path: %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we deallocate the result structure memory
+ CleanUp return_cleanup([process, return_addr] {
+ process->DeallocateMemory(return_addr);
+ });
+
+ // This will be the address of the storage for paths, if we are using them,
+ // or nullptr to signal we aren't.
+ lldb::addr_t path_array_addr = 0x0;
+ llvm::Optional<CleanUp> path_array_cleanup;
+
+ // This is the address to a buffer large enough to hold the largest path
+ // conjoined with the library name we're passing in. This is a convenience
+ // to avoid having to call malloc in the dlopen function.
+ lldb::addr_t buffer_addr = 0x0;
+ llvm::Optional<CleanUp> buffer_cleanup;
+
+ // Set the values into our args and write them to the target:
+ if (paths != nullptr) {
+ // First insert the paths into the target. This is expected to be a
+ // continuous buffer with the strings laid out null terminated and
+ // end to end with an empty string terminating the buffer.
+ // We also compute the buffer's required size as we go.
+ size_t buffer_size = 0;
+ std::string path_array;
+ for (auto path : *paths) {
+ // Don't insert empty paths, they will make us abort the path
+ // search prematurely.
+ if (path.empty())
+ continue;
+ size_t path_size = path.size();
+ path_array.append(path);
+ path_array.push_back('\0');
+ if (path_size > buffer_size)
+ buffer_size = path_size;
+ }
+ path_array.push_back('\0');
+
+ path_array_addr = process->AllocateMemory(path_array.size(),
+ permissions,
+ utility_error);
+ if (path_array_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for path array: %s",
+ utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we deallocate the paths array.
+ path_array_cleanup.emplace([process, path_array_addr] {
+ process->DeallocateMemory(path_array_addr);
+ });
+
+ process->WriteMemory(path_array_addr, path_array.data(),
+ path_array.size(), utility_error);
+
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not write path array:"
+ " %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+ // Now make spaces in the target for the buffer. We need to add one for
+ // the '/' that the utility function will insert and one for the '\0':
+ buffer_size += path.size() + 2;
+
+ buffer_addr = process->AllocateMemory(buffer_size,
+ permissions,
+ utility_error);
+ if (buffer_addr == LLDB_INVALID_ADDRESS) {
+ error.SetErrorStringWithFormat("dlopen error: could not allocate memory"
+ "for buffer: %s",
+ utility_error.AsCString());
return LLDB_INVALID_IMAGE_TOKEN;
}
+
+ // Make sure we deallocate the buffer memory:
+ buffer_cleanup.emplace([process, buffer_addr] {
+ process->DeallocateMemory(buffer_addr);
+ });
}
- error.SetErrorStringWithFormat("unable to load '%s'", path);
+
+ arguments.GetValueAtIndex(0)->GetScalar() = path_addr;
+ arguments.GetValueAtIndex(1)->GetScalar() = path_array_addr;
+ arguments.GetValueAtIndex(2)->GetScalar() = buffer_addr;
+ arguments.GetValueAtIndex(3)->GetScalar() = return_addr;
+
+ lldb::addr_t func_args_addr = LLDB_INVALID_ADDRESS;
+
+ diagnostics.Clear();
+ if (!do_dlopen_function->WriteFunctionArguments(exe_ctx,
+ func_args_addr,
+ arguments,
+ diagnostics)) {
+ error.SetErrorStringWithFormat("dlopen error: could not write function "
+ "arguments: %s",
+ diagnostics.GetString().c_str());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Make sure we clean up the args structure. We can't reuse it because the
+ // Platform lives longer than the process and the Platforms don't get a
+ // signal to clean up cached data when a process goes away.
+ CleanUp args_cleanup([do_dlopen_function, &exe_ctx, func_args_addr] {
+ do_dlopen_function->DeallocateFunctionResults(exe_ctx, func_args_addr);
+ });
+
+ // Now run the caller:
+ EvaluateExpressionOptions options;
+ options.SetExecutionPolicy(eExecutionPolicyAlways);
+ options.SetLanguage(eLanguageTypeC_plus_plus);
+ options.SetIgnoreBreakpoints(true);
+ options.SetUnwindOnError(true);
+ options.SetTrapExceptions(false); // dlopen can't throw exceptions, so
+ // don't do the work to trap them.
+ options.SetTimeout(std::chrono::seconds(2));
+
+ Value return_value;
+ // Fetch the clang types we will need:
+ ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+
+ CompilerType clang_void_pointer_type
+ = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ return_value.SetCompilerType(clang_void_pointer_type);
+
+ ExpressionResults results = do_dlopen_function->ExecuteFunction(
+ exe_ctx, &func_args_addr, options, diagnostics, return_value);
+ if (results != eExpressionCompleted) {
+ error.SetErrorStringWithFormat("dlopen error: failed executing "
+ "dlopen wrapper function: %s",
+ diagnostics.GetString().c_str());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // Read the dlopen token from the return area:
+ lldb::addr_t token = process->ReadPointerFromMemory(return_addr,
+ utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not read the return "
+ "struct: %s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ // The dlopen succeeded!
+ if (token != 0x0) {
+ if (loaded_image && buffer_addr != 0x0)
+ {
+ // Capture the image which was loaded. We leave it in the buffer on
+ // exit from the dlopen function, so we can just read it from there:
+ std::string name_string;
+ process->ReadCStringFromMemory(buffer_addr, name_string, utility_error);
+ if (utility_error.Success())
+ loaded_image->SetFile(name_string, false,
+ llvm::sys::path::Style::posix);
+ }
+ return process->AddImageToken(token);
+ }
+
+ // We got an error, lets read in the error string:
+ std::string dlopen_error_str;
+ lldb::addr_t error_addr
+ = process->ReadPointerFromMemory(return_addr + addr_size, utility_error);
+ if (utility_error.Fail()) {
+ error.SetErrorStringWithFormat("dlopen error: could not read error string: "
+ "%s", utility_error.AsCString());
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ size_t num_chars = process->ReadCStringFromMemory(error_addr + addr_size,
+ dlopen_error_str,
+ utility_error);
+ if (utility_error.Success() && num_chars > 0)
+ error.SetErrorStringWithFormat("dlopen error: %s",
+ dlopen_error_str.c_str());
+ else
+ error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
+
return LLDB_INVALID_IMAGE_TOKEN;
}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 93bebeb332ca..cc6f7299c194 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -85,7 +85,7 @@ public:
const lldb::UnixSignalsSP &GetRemoteUnixSignals() override;
- size_t GetEnvironment(lldb_private::StringList &environment) override;
+ lldb_private::Environment GetEnvironment() override;
bool IsConnected() const override;
@@ -99,8 +99,7 @@ public:
// the process to exit
std::string
*command_output, // Pass nullptr if you don't want the command output
- uint32_t timeout_sec)
- override; // Timeout in seconds to wait for shell program to finish
+ const lldb_private::Timeout<std::micro> &timeout) override;
lldb_private::Status ResolveExecutable(
const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
@@ -166,7 +165,9 @@ public:
uint32_t DoLoadImage(lldb_private::Process *process,
const lldb_private::FileSpec &remote_file,
- lldb_private::Status &error) override;
+ const std::vector<std::string> *paths,
+ lldb_private::Status &error,
+ lldb_private::FileSpec *loaded_image) override;
lldb_private::Status UnloadImage(lldb_private::Process *process,
uint32_t image_token) override;
@@ -201,6 +202,10 @@ protected:
llvm::StringRef expr_prefix,
lldb::ValueObjectSP &result_valobj_sp);
+ std::unique_ptr<lldb_private::UtilityFunction>
+ MakeLoadImageUtilityFunction(lldb_private::ExecutionContext &exe_ctx,
+ lldb_private::Status &error);
+
virtual
llvm::StringRef GetLibdlFunctionDeclarations(lldb_private::Process *process);
diff --git a/source/Plugins/Platform/Windows/PlatformWindows.cpp b/source/Plugins/Platform/Windows/PlatformWindows.cpp
index 3535df0c65cc..ed2bcf0cbee4 100644
--- a/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ b/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -194,7 +194,8 @@ Status PlatformWindows::ResolveExecutable(
// variables
if (!resolved_module_spec.GetFileSpec().Exists()) {
resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
- resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true,
+ FileSpec::Style::native);
}
if (!resolved_module_spec.GetFileSpec().Exists())
@@ -237,9 +238,9 @@ Status PlatformWindows::ResolveExecutable(
resolved_module_spec.GetArchitecture().GetArchitectureName());
}
} else {
- // No valid architecture was specified, ask the platform for
- // the architectures that we should be using (in the correct order)
- // and see if we can find a match that way
+ // No valid architecture was specified, ask the platform for the
+ // architectures that we should be using (in the correct order) and see
+ // if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
@@ -279,9 +280,10 @@ Status PlatformWindows::ResolveExecutable(
}
bool PlatformWindows::GetRemoteOSVersion() {
- if (m_remote_platform_sp)
- return m_remote_platform_sp->GetOSVersion(
- m_major_os_version, m_minor_os_version, m_update_os_version);
+ if (m_remote_platform_sp) {
+ m_os_version = m_remote_platform_sp->GetOSVersion();
+ return !m_os_version.empty();
+ }
return false;
}
@@ -413,29 +415,23 @@ ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info,
Debugger &debugger, Target *target,
Status &error) {
// Windows has special considerations that must be followed when launching or
- // attaching to a process. The
- // key requirement is that when launching or attaching to a process, you must
- // do it from the same the thread
- // that will go into a permanent loop which will then receive debug events
- // from the process. In particular,
- // this means we can't use any of LLDB's generic mechanisms to do it for us,
- // because it doesn't have the
- // special knowledge required for setting up the background thread or passing
- // the right flags.
+ // attaching to a process. The key requirement is that when launching or
+ // attaching to a process, you must do it from the same the thread that will
+ // go into a permanent loop which will then receive debug events from the
+ // process. In particular, this means we can't use any of LLDB's generic
+ // mechanisms to do it for us, because it doesn't have the special knowledge
+ // required for setting up the background thread or passing the right flags.
//
// Another problem is that that LLDB's standard model for debugging a process
- // is to first launch it, have
- // it stop at the entry point, and then attach to it. In Windows this doesn't
- // quite work, you have to
- // specify as an argument to CreateProcess() that you're going to debug the
- // process. So we override DebugProcess
- // here to handle this. Launch operations go directly to the process plugin,
- // and attach operations almost go
- // directly to the process plugin (but we hijack the events first). In
- // essence, we encapsulate all the logic
- // of Launching and Attaching in the process plugin, and
- // PlatformWindows::DebugProcess is just a pass-through
- // to get to the process plugin.
+ // is to first launch it, have it stop at the entry point, and then attach to
+ // it. In Windows this doesn't quite work, you have to specify as an
+ // argument to CreateProcess() that you're going to debug the process. So we
+ // override DebugProcess here to handle this. Launch operations go directly
+ // to the process plugin, and attach operations almost go directly to the
+ // process plugin (but we hijack the events first). In essence, we
+ // encapsulate all the logic of Launching and Attaching in the process
+ // plugin, and PlatformWindows::DebugProcess is just a pass-through to get to
+ // the process plugin.
if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
// This is a process attach. Don't need to launch anything.
@@ -538,8 +534,8 @@ Status PlatformWindows::GetSharedModule(
module_sp.reset();
if (IsRemote()) {
- // If we have a remote platform always, let it try and locate
- // the shared module first.
+ // If we have a remote platform always, let it try and locate the shared
+ // module first.
if (m_remote_platform_sp) {
error = m_remote_platform_sp->GetSharedModule(
module_spec, process, module_sp, module_search_paths_ptr,
@@ -572,29 +568,21 @@ void PlatformWindows::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
#ifdef _WIN32
- uint32_t major;
- uint32_t minor;
- uint32_t update;
- if (!HostInfo::GetOSVersion(major, minor, update)) {
- strm << "Windows";
- return;
- }
-
- strm << "Host: Windows " << major << '.' << minor << " Build: " << update
- << '\n';
+ llvm::VersionTuple version = HostInfo::GetOSVersion();
+ strm << "Host: Windows " << version.getAsString() << '\n';
#endif
}
bool PlatformWindows::CanDebugProcess() { return true; }
-size_t PlatformWindows::GetEnvironment(StringList &env) {
+Environment PlatformWindows::GetEnvironment() {
if (IsRemote()) {
if (m_remote_platform_sp)
- return m_remote_platform_sp->GetEnvironment(env);
- return 0;
+ return m_remote_platform_sp->GetEnvironment();
+ return Environment();
}
- return Host::GetEnvironment(env);
+ return Host::GetEnvironment();
}
ConstString PlatformWindows::GetFullNameForDylib(ConstString basename) {
diff --git a/source/Plugins/Platform/Windows/PlatformWindows.h b/source/Plugins/Platform/Windows/PlatformWindows.h
index 9af42116680e..3a15271c5762 100644
--- a/source/Plugins/Platform/Windows/PlatformWindows.h
+++ b/source/Plugins/Platform/Windows/PlatformWindows.h
@@ -118,7 +118,7 @@ public:
bool CanDebugProcess() override;
- size_t GetEnvironment(StringList &env) override;
+ Environment GetEnvironment() override;
// FIXME not sure what the _sigtramp equivalent would be on this platform
void CalculateTrapHandlerSymbolNames() override {}
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 759ec7fd1d29..348bb825a5c5 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -118,9 +118,9 @@ Status PlatformRemoteGDBServer::ResolveExecutable(
return error;
exe_module_sp.reset();
}
- // No valid architecture was specified or the exact arch wasn't
- // found so ask the platform for the architectures that we should be
- // using (in the correct order) and see if we can find a match that way
+ // No valid architecture was specified or the exact arch wasn't found so
+ // ask the platform for the architectures that we should be using (in the
+ // correct order) and see if we can find a match that way
StreamString arch_names;
for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
idx, resolved_module_spec.GetArchitecture());
@@ -236,14 +236,8 @@ size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode(
}
bool PlatformRemoteGDBServer::GetRemoteOSVersion() {
- uint32_t major, minor, update;
- if (m_gdb_client.GetOSVersion(major, minor, update)) {
- m_major_os_version = major;
- m_minor_os_version = minor;
- m_update_os_version = update;
- return true;
- }
- return false;
+ m_os_version = m_gdb_client.GetOSVersion();
+ return !m_os_version.empty();
}
bool PlatformRemoteGDBServer::GetRemoteOSBuildString(std::string &s) {
@@ -277,8 +271,7 @@ bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory(
const FileSpec &working_dir) {
if (IsConnected()) {
// Clear the working directory it case it doesn't get set correctly. This
- // will
- // for use to re-read it
+ // will for use to re-read it
Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
if (log)
log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')",
@@ -423,16 +416,7 @@ Status PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) {
}
// Send the environment and the program + arguments after we connect
- const char **envp =
- launch_info.GetEnvironmentEntries().GetConstArgumentVector();
-
- if (envp) {
- const char *env_entry;
- for (int i = 0; (env_entry = envp[i]); ++i) {
- if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0)
- break;
- }
- }
+ m_gdb_client.SendEnvironment(launch_info.GetEnvironment());
ArchSpec arch_spec = launch_info.GetArchitecture();
const char *arch_triple = arch_spec.GetTriple().str().c_str();
@@ -549,9 +533,8 @@ bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid,
bool launch_result = false;
if (remote_triple.getVendor() == llvm::Triple::Apple &&
remote_triple.getOS() == llvm::Triple::IOS) {
- // When remote debugging to iOS, we use a USB mux that always talks
- // to localhost, so we will need the remote debugserver to accept
- // connections
+ // When remote debugging to iOS, we use a USB mux that always talks to
+ // localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
launch_result =
m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name);
@@ -731,11 +714,9 @@ Status PlatformRemoteGDBServer::RunShellCommand(
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t
- timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
+ const Timeout<std::micro> &timeout) {
return m_gdb_client.RunShellCommand(command, working_dir, status_ptr,
- signo_ptr, command_output, timeout_sec);
+ signo_ptr, command_output, timeout);
}
void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() {
@@ -749,8 +730,8 @@ const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() {
if (m_remote_signals_sp)
return m_remote_signals_sp;
- // If packet not implemented or JSON failed to parse,
- // we'll guess the signal set based on the remote architecture.
+ // If packet not implemented or JSON failed to parse, we'll guess the signal
+ // set based on the remote architecture.
m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
StringExtractorGDBRemote response;
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 210544f752e6..a31933b5d9b0 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -17,7 +17,7 @@
// Other libraries and framework includes
// Project includes
-#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h"
+#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "lldb/Target/Platform.h"
@@ -155,8 +155,7 @@ public:
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t timeout_sec)
- override; // Timeout in seconds to wait for shell program to finish
+ const lldb_private::Timeout<std::micro> &timeout) override;
void CalculateTrapHandlerSymbolNames() override;
diff --git a/source/Plugins/Process/CMakeLists.txt b/source/Plugins/Process/CMakeLists.txt
index 62abd75a43b6..fdeb211fe7a2 100644
--- a/source/Plugins/Process/CMakeLists.txt
+++ b/source/Plugins/Process/CMakeLists.txt
@@ -11,9 +11,9 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
add_subdirectory(Windows/Common)
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX-Kernel)
- add_subdirectory(mach-core)
endif()
add_subdirectory(gdb-remote)
add_subdirectory(Utility)
add_subdirectory(elf-core)
+add_subdirectory(mach-core)
add_subdirectory(minidump)
diff --git a/source/Plugins/Process/Darwin/CFString.cpp b/source/Plugins/Process/Darwin/CFString.cpp
index 84ad56774d7c..b87afe999181 100644
--- a/source/Plugins/Process/Darwin/CFString.cpp
+++ b/source/Plugins/Process/Darwin/CFString.cpp
@@ -91,9 +91,8 @@ const char *CFString::UTF8(std::string &str) {
return CFString::UTF8(get(), str);
}
-// Static function that puts a copy of the UTF8 contents of CF_STR into STR
-// and returns the C string pointer that is contained in STR when successful,
-// else
+// Static function that puts a copy of the UTF8 contents of CF_STR into STR and
+// returns the C string pointer that is contained in STR when successful, else
// NULL is returned. This allows the std::string parameter to own the extracted
// string,
// and also allows that string to be returned as a C string pointer that can be
@@ -120,9 +119,9 @@ const char *CFString::UTF8(CFStringRef cf_str, std::string &str) {
// Static function that puts a copy of the file system representation of CF_STR
// into STR and returns the C string pointer that is contained in STR when
-// successful, else NULL is returned. This allows the std::string parameter
-// to own the extracted string, and also allows that string to be returned as
-// a C string pointer that can be used.
+// successful, else NULL is returned. This allows the std::string parameter to
+// own the extracted string, and also allows that string to be returned as a C
+// string pointer that can be used.
const char *CFString::FileSystemRepresentation(CFStringRef cf_str,
std::string &str) {
diff --git a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
index 6b3d5f6c117f..95659725ce2e 100644
--- a/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
+++ b/source/Plugins/Process/Darwin/DarwinProcessLauncher.cpp
@@ -142,8 +142,8 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[],
}
// Use a fork that ties the child process's stdin/out/err to a pseudo
- // terminal so we can read it in our MachProcess::STDIOThread
- // as unbuffered io.
+ // terminal so we can read it in our MachProcess::STDIOThread as unbuffered
+ // io.
PseudoTerminal pty;
char fork_error[256];
memset(fork_error, 0, sizeof(fork_error));
@@ -167,12 +167,12 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[],
// Get BSD signals as mach exceptions.
::ptrace(PT_SIGEXC, 0, 0, 0);
- // If our parent is setgid, lets make sure we don't inherit those
- // extra powers due to nepotism.
+ // If our parent is setgid, lets make sure we don't inherit those extra
+ // powers due to nepotism.
if (::setgid(getgid()) == 0) {
- // Let the child have its own process group. We need to execute
- // this call in both the child and parent to avoid a race
- // condition between the two processes.
+ // Let the child have its own process group. We need to execute this call
+ // in both the child and parent to avoid a race condition between the two
+ // processes.
// Set the child process group to match its pid.
::setpgid(0, 0);
@@ -183,23 +183,22 @@ static Status ForkChildForPTraceDebugging(const char *path, char const *argv[],
// Turn this process into the given executable.
::execv(path, (char *const *)argv);
}
- // Exit with error code. Child process should have taken
- // over in above exec call and if the exec fails it will
- // exit the child process below.
+ // Exit with error code. Child process should have taken over in above exec
+ // call and if the exec fails it will exit the child process below.
::exit(127);
} else {
//--------------------------------------------------------------
// Parent process
//--------------------------------------------------------------
- // Let the child have its own process group. We need to execute
- // this call in both the child and parent to avoid a race condition
- // between the two processes.
+ // Let the child have its own process group. We need to execute this call
+ // in both the child and parent to avoid a race condition between the two
+ // processes.
// Set the child process group to match its pid
::setpgid(*pid, *pid);
if (pty_fd) {
- // Release our master pty file descriptor so the pty class doesn't
- // close it and so we can continue to use it in our STDIO thread
+ // Release our master pty file descriptor so the pty class doesn't close
+ // it and so we can continue to use it in our STDIO thread
*pty_fd = pty.ReleaseMasterFileDescriptor();
}
}
@@ -302,8 +301,7 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
return error;
}
- // Ensure we clean up the spawnattr structure however we exit this
- // function.
+ // Ensure we clean up the spawnattr structure however we exit this function.
std::unique_ptr<posix_spawnattr_t, int (*)(posix_spawnattr_t *)> spawnattr_up(
&attr, ::posix_spawnattr_destroy);
@@ -332,9 +330,9 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
#if !defined(__arm__)
- // We don't need to do this for ARM, and we really shouldn't now that we
- // have multiple CPU subtypes and no posix_spawnattr call that allows us
- // to set which CPU subtype to launch...
+ // We don't need to do this for ARM, and we really shouldn't now that we have
+ // multiple CPU subtypes and no posix_spawnattr call that allows us to set
+ // which CPU subtype to launch...
cpu_type_t desired_cpu_type = launch_info.GetArchitecture().GetMachOCPUType();
if (desired_cpu_type != LLDB_INVALID_CPUTYPE) {
size_t ocount = 0;
@@ -374,10 +372,10 @@ static Status PosixSpawnChildForPTraceDebugging(const char *path,
int (*)(posix_spawn_file_actions_t *)>
file_actions_up(&file_actions, ::posix_spawn_file_actions_destroy);
- // We assume the caller has setup the file actions appropriately. We
- // are not in the business of figuring out what we really need here.
- // lldb-server will have already called FinalizeFileActions() as well
- // to button these up properly.
+ // We assume the caller has setup the file actions appropriately. We are not
+ // in the business of figuring out what we really need here. lldb-server will
+ // have already called FinalizeFileActions() as well to button these up
+ // properly.
const size_t num_actions = launch_info.GetNumFileActions();
for (size_t action_index = 0; action_index < num_actions; ++action_index) {
const FileAction *const action =
@@ -533,8 +531,8 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
if (error.Success()) {
launch_info.SetProcessID(static_cast<lldb::pid_t>(pid));
} else {
- // Reset any variables that might have been set during a failed
- // launch attempt.
+ // Reset any variables that might have been set during a failed launch
+ // attempt.
if (pty_master_fd)
*pty_master_fd = -1;
@@ -616,8 +614,8 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
if (pty_master_fd)
*pty_master_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
} else {
- // Reset any variables that might have been set during a failed
- // launch attempt.
+ // Reset any variables that might have been set during a failed launch
+ // attempt.
if (pty_master_fd)
*pty_master_fd = -1;
@@ -636,8 +634,8 @@ Status LaunchInferior(ProcessLaunchInfo &launch_info, int *pty_master_fd,
}
if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
- // If we don't have a valid process ID and no one has set the error,
- // then return a generic error.
+ // If we don't have a valid process ID and no one has set the error, then
+ // return a generic error.
if (error.Success())
error.SetErrorStringWithFormat("%s(): failed to launch, no reason "
"specified",
diff --git a/source/Plugins/Process/Darwin/MachException.cpp b/source/Plugins/Process/Darwin/MachException.cpp
index 9f5920753d68..353f2df32139 100644
--- a/source/Plugins/Process/Darwin/MachException.cpp
+++ b/source/Plugins/Process/Darwin/MachException.cpp
@@ -92,8 +92,6 @@ extern "C" kern_return_t catch_mach_exception_raise_state_identity(
(uint64_t)(exc_data_count > 0 ? exc_data[0] : 0xBADDBADD),
(uint64_t)(exc_data_count > 1 ? exc_data[1] : 0xBADDBADD));
}
- mach_port_deallocate(mach_task_self(), task_port);
- mach_port_deallocate(mach_task_self(), thread_port);
return KERN_FAILURE;
}
@@ -249,20 +247,19 @@ bool MachException::Message::CatchExceptionRaise(task_t task) {
bool success = false;
state.task_port = task;
g_message = &state;
- // The exc_server function is the MIG generated server handling function
- // to handle messages from the kernel relating to the occurrence of an
- // exception in a thread. Such messages are delivered to the exception port
- // set via thread_set_exception_ports or task_set_exception_ports. When an
- // exception occurs in a thread, the thread sends an exception message to
- // its exception port, blocking in the kernel waiting for the receipt of a
- // reply. The exc_server function performs all necessary argument handling
- // for this kernel message and calls catch_exception_raise,
- // catch_exception_raise_state or catch_exception_raise_state_identity,
- // which should handle the exception. If the called routine returns
- // KERN_SUCCESS, a reply message will be sent, allowing the thread to
- // continue from the point of the exception; otherwise, no reply message
- // is sent and the called routine must have dealt with the exception
- // thread directly.
+ // The exc_server function is the MIG generated server handling function to
+ // handle messages from the kernel relating to the occurrence of an exception
+ // in a thread. Such messages are delivered to the exception port set via
+ // thread_set_exception_ports or task_set_exception_ports. When an exception
+ // occurs in a thread, the thread sends an exception message to its exception
+ // port, blocking in the kernel waiting for the receipt of a reply. The
+ // exc_server function performs all necessary argument handling for this
+ // kernel message and calls catch_exception_raise,
+ // catch_exception_raise_state or catch_exception_raise_state_identity, which
+ // should handle the exception. If the called routine returns KERN_SUCCESS, a
+ // reply message will be sent, allowing the thread to continue from the point
+ // of the exception; otherwise, no reply message is sent and the called
+ // routine must have dealt with the exception thread directly.
if (mach_exc_server(&exc_msg.hdr, &reply_msg.hdr)) {
success = true;
} else {
@@ -385,9 +382,9 @@ Status MachException::PortInfo::Save(task_t task) {
log->Printf("MachException::PortInfo::%s(task = 0x%4.4x)", __FUNCTION__,
task);
- // Be careful to be able to have debugserver built on a newer OS than what
- // it is currently running on by being able to start with all exceptions
- // and back off to just what is supported on the current system
+ // Be careful to be able to have debugserver built on a newer OS than what it
+ // is currently running on by being able to start with all exceptions and
+ // back off to just what is supported on the current system
mask = LLDB_EXC_MASK;
count = (sizeof(ports) / sizeof(ports[0]));
diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
index 518f0d2da4f2..3505443abcb0 100644
--- a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
+++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
@@ -104,8 +104,8 @@ Status NativeProcessProtocol::Launch(
return error;
}
- // Finalize the processing needed to debug the launched process with
- // a NativeProcessDarwin instance.
+ // Finalize the processing needed to debug the launched process with a
+ // NativeProcessDarwin instance.
error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop);
if (!error.Success()) {
if (log)
@@ -194,9 +194,9 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
"mach exception port monitor thread: %s",
__FUNCTION__, error.AsCString());
- // Terminate the inferior process. There's nothing meaningful we can
- // do if we can't receive signals and exceptions. Since we launched
- // the process, it's fair game for us to kill it.
+ // Terminate the inferior process. There's nothing meaningful we can do if
+ // we can't receive signals and exceptions. Since we launched the process,
+ // it's fair game for us to kill it.
::ptrace(PT_KILL, m_pid, 0, 0);
SetState(eStateExited);
@@ -243,9 +243,9 @@ Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
}
if (TaskPortForProcessID(error) == TASK_NULL) {
- // We failed to get the task for our process ID which is bad.
- // Kill our process; otherwise, it will be stopped at the entry
- // point and get reparented to someone else and never go away.
+ // We failed to get the task for our process ID which is bad. Kill our
+ // process; otherwise, it will be stopped at the entry point and get
+ // reparented to someone else and never go away.
if (log)
log->Printf("NativeProcessDarwin::%s(): could not get task port "
"for process, sending SIGKILL and exiting: %s",
@@ -277,9 +277,9 @@ bool NativeProcessDarwin::ProcessUsingBackBoard() const {
return false;
}
-// Called by the exception thread when an exception has been received from
-// our process. The exception message is completely filled and the exception
-// data has already been copied.
+// Called by the exception thread when an exception has been received from our
+// process. The exception message is completely filled and the exception data
+// has already been copied.
void NativeProcessDarwin::ExceptionMessageReceived(
const MachException::Message &message) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
@@ -290,8 +290,8 @@ void NativeProcessDarwin::ExceptionMessageReceived(
SuspendTask();
}
- // Use a locker to automatically unlock our mutex in case of exceptions
- // Add the exception to our internal exception stack
+ // Use a locker to automatically unlock our mutex in case of exceptions Add
+ // the exception to our internal exception stack
m_exception_messages.push_back(message);
if (log)
@@ -324,13 +324,12 @@ void *NativeProcessDarwin::DoExceptionThread() {
// Ensure we don't get CPU starved.
MaybeRaiseThreadPriority();
- // We keep a count of the number of consecutive exceptions received so
- // we know to grab all exceptions without a timeout. We do this to get a
- // bunch of related exceptions on our exception port so we can process
- // then together. When we have multiple threads, we can get an exception
- // per thread and they will come in consecutively. The main loop in this
- // thread can stop periodically if needed to service things related to this
- // process.
+ // We keep a count of the number of consecutive exceptions received so we
+ // know to grab all exceptions without a timeout. We do this to get a bunch
+ // of related exceptions on our exception port so we can process then
+ // together. When we have multiple threads, we can get an exception per
+ // thread and they will come in consecutively. The main loop in this thread
+ // can stop periodically if needed to service things related to this process.
//
// [did we lose some words here?]
//
@@ -338,15 +337,15 @@ void *NativeProcessDarwin::DoExceptionThread() {
// 0 our exception port. After we get one exception, we then will use the
// MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
// exceptions for our process. After we have received the last pending
- // exception, we will get a timeout which enables us to then notify
- // our main thread that we have an exception bundle available. We then wait
- // for the main thread to tell this exception thread to start trying to get
+ // exception, we will get a timeout which enables us to then notify our main
+ // thread that we have an exception bundle available. We then wait for the
+ // main thread to tell this exception thread to start trying to get
// exceptions messages again and we start again with a mach_msg read with
// infinite timeout.
//
// We choose to park a thread on this, rather than polling, because the
- // polling is expensive. On devices, we need to minimize overhead caused
- // by the process monitor.
+ // polling is expensive. On devices, we need to minimize overhead caused by
+ // the process monitor.
uint32_t num_exceptions_received = 0;
Status error;
task_t task = m_task;
@@ -359,8 +358,7 @@ void *NativeProcessDarwin::DoExceptionThread() {
CFReleaser<SBSWatchdogAssertionRef> watchdog;
if (process->ProcessUsingSpringBoard()) {
- // Request a renewal for every 60 seconds if we attached using
- // SpringBoard.
+ // Request a renewal for every 60 seconds if we attached using SpringBoard.
watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60));
if (log)
log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
@@ -401,18 +399,18 @@ void *NativeProcessDarwin::DoExceptionThread() {
}
#endif // #ifdef WITH_BKS
- // Do we want to use a weak pointer to the NativeProcessDarwin here, in
- // which case we can guarantee we don't whack the process monitor if we
- // race between this thread and the main one on shutdown?
+ // Do we want to use a weak pointer to the NativeProcessDarwin here, in which
+ // case we can guarantee we don't whack the process monitor if we race
+ // between this thread and the main one on shutdown?
while (IsExceptionPortValid()) {
::pthread_testcancel();
MachException::Message exception_message;
if (num_exceptions_received > 0) {
- // We don't want a timeout here, just receive as many exceptions as
- // we can since we already have one. We want to get all currently
- // available exceptions for this task at once.
+ // We don't want a timeout here, just receive as many exceptions as we
+ // can since we already have one. We want to get all currently available
+ // exceptions for this task at once.
error = exception_message.Receive(
GetExceptionPort(),
MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0);
@@ -424,8 +422,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
MACH_RCV_TIMEOUT,
periodic_timeout);
} else {
- // We don't need to parse all current exceptions or stop
- // periodically, just wait for an exception forever.
+ // We don't need to parse all current exceptions or stop periodically,
+ // just wait for an exception forever.
error = exception_message.Receive(GetExceptionPort(),
MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0);
}
@@ -462,8 +460,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
__FUNCTION__);
continue;
} else {
- // The inferior task is no longer valid. Time to exit as
- // the process has gone away.
+ // The inferior task is no longer valid. Time to exit as the process
+ // has gone away.
if (log)
log->Printf("NativeProcessDarwin::%s(): the inferior task "
"has exited, and so will we...",
@@ -476,18 +474,17 @@ void *NativeProcessDarwin::DoExceptionThread() {
// We timed out when waiting for exceptions.
if (num_exceptions_received > 0) {
- // We were receiving all current exceptions with a timeout of
- // zero. It is time to go back to our normal looping mode.
+ // We were receiving all current exceptions with a timeout of zero.
+ // It is time to go back to our normal looping mode.
num_exceptions_received = 0;
- // Notify our main thread we have a complete exception message
- // bundle available. Get the possibly updated task port back
- // from the process in case we exec'ed and our task port
- // changed.
+ // Notify our main thread we have a complete exception message bundle
+ // available. Get the possibly updated task port back from the
+ // process in case we exec'ed and our task port changed.
task = ExceptionMessageBundleComplete();
- // In case we use a timeout value when getting exceptions,
- // make sure our task is still valid.
+ // In case we use a timeout value when getting exceptions, make sure
+ // our task is still valid.
if (IsTaskValid(task)) {
// Task is still ok.
if (log)
@@ -496,8 +493,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
__FUNCTION__);
continue;
} else {
- // The inferior task is no longer valid. Time to exit as
- // the process has gone away.
+ // The inferior task is no longer valid. Time to exit as the
+ // process has gone away.
if (log)
log->Printf("NativeProcessDarwin::%s(): the inferior "
"task has exited, and so will we...",
@@ -534,10 +531,8 @@ void *NativeProcessDarwin::DoExceptionThread() {
// TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel
// when we
// all are up and running on systems that support it. The SBS framework has
- // a #define
- // that will forward SBSWatchdogAssertionRelease to
- // SBSWatchdogAssertionCancel for now
- // so it should still build either way.
+ // a #define that will forward SBSWatchdogAssertionRelease to
+ // SBSWatchdogAssertionCancel for now so it should still build either way.
DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)",
watchdog.get());
::SBSWatchdogAssertionRelease(watchdog.get());
@@ -728,8 +723,8 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
const int signo = m_exception_messages[i].state.SoftSignal();
if (signo == SIGTRAP) {
// SIGTRAP could mean that we exec'ed. We need to check the
- // dyld all_image_infos.infoArray to see if it is NULL and if
- // so, say that we exec'ed.
+ // dyld all_image_infos.infoArray to see if it is NULL and if so, say
+ // that we exec'ed.
const addr_t aii_addr = GetDYLDAllImageInfosAddress(error);
if (aii_addr == LLDB_INVALID_ADDRESS)
break;
@@ -744,12 +739,12 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
bytes_read); // #bytes read
if (read_error.Success() && (bytes_read == 4)) {
if (info_array_count == 0) {
- // We got the all infos address, and there are zero
- // entries. We think we exec'd.
+ // We got the all infos address, and there are zero entries. We
+ // think we exec'd.
m_did_exec = true;
- // Force the task port to update itself in case the
- // task port changed after exec
+ // Force the task port to update itself in case the task port
+ // changed after exec
const task_t old_task = m_task;
const bool force_update = true;
const task_t new_task = TaskPortForProcessID(error, force_update);
@@ -810,8 +805,7 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
// 4 - We might need to resume if we stopped only with the
// interrupt signal that we never handled.
if (m_auto_resume_signo != 0) {
- // Only auto_resume if we stopped with _only_ the interrupt
- // signal.
+ // Only auto_resume if we stopped with _only_ the interrupt signal.
if (num_task_exceptions == 1) {
auto_resume = true;
if (log)
@@ -831,8 +825,8 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
}
}
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
m_thread_list.ProcessDidStop(*this);
// Let each thread know of any exceptions
@@ -863,8 +857,8 @@ task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
// TODO - need to hook up event system here. !!!!
#if 0
// Wait for the eEventProcessRunningStateChanged event to be reset
- // before changing state to stopped to avoid race condition with
- // very fast start/stops.
+ // before changing state to stopped to avoid race condition with very
+ // fast start/stops.
struct timespec timeout;
//DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000); // Wait for 250 ms
@@ -889,12 +883,12 @@ Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) {
Status error;
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- // Strategy: create a thread that sits on waitpid(), waiting for the
- // inferior process to die, reaping it in the process. Arrange for
- // the thread to have a pipe file descriptor that it can send a byte
- // over when the waitpid completes. Have the main loop have a read
- // object for the other side of the pipe, and have the callback for
- // the read do the process termination message sending.
+ // Strategy: create a thread that sits on waitpid(), waiting for the inferior
+ // process to die, reaping it in the process. Arrange for the thread to have
+ // a pipe file descriptor that it can send a byte over when the waitpid
+ // completes. Have the main loop have a read object for the other side of
+ // the pipe, and have the callback for the read do the process termination
+ // message sending.
// Create a single-direction communication channel.
const bool child_inherits = false;
@@ -1025,8 +1019,8 @@ void *NativeProcessDarwin::DoWaitpidThread() {
}
}
- // We should never exit as long as our child process is alive. If we
- // get here, something completely unexpected went wrong and we should exit.
+ // We should never exit as long as our child process is alive. If we get
+ // here, something completely unexpected went wrong and we should exit.
if (log)
log->Printf(
"NativeProcessDarwin::%s(): internal error: waitpid thread "
@@ -1157,8 +1151,8 @@ task_t NativeProcessDarwin::TaskPortForProcessID(Status &error,
::usleep(usec_interval);
}
- // We failed to get the task for the inferior process.
- // Ensure that it is cleared out.
+ // We failed to get the task for the inferior process. Ensure that it is
+ // cleared out.
m_task = TASK_NULL;
}
return m_task;
@@ -1196,9 +1190,9 @@ Status NativeProcessDarwin::PrivateResume() {
}
// bool stepOverBreakInstruction = step;
- // Let the thread prepare to resume and see if any threads want us to
- // step over a breakpoint instruction (ProcessWillResume will modify
- // the value of stepOverBreakInstruction).
+ // Let the thread prepare to resume and see if any threads want us to step
+ // over a breakpoint instruction (ProcessWillResume will modify the value of
+ // stepOverBreakInstruction).
m_thread_list.ProcessWillResume(*this, m_thread_actions);
// Set our state accordingly
@@ -1254,8 +1248,8 @@ Status NativeProcessDarwin::ReplyToAllExceptions() {
error = message.Reply(m_pid, m_task, thread_reply_signal);
if (error.Fail() && log) {
- // We log any error here, but we don't stop the exception
- // response handling.
+ // We log any error here, but we don't stop the exception response
+ // handling.
log->Printf("NativeProcessDarwin::%s(): failed to reply to "
"exception: %s",
__FUNCTION__, error.AsCString());
@@ -1263,8 +1257,8 @@ Status NativeProcessDarwin::ReplyToAllExceptions() {
}
}
- // Erase all exception message as we should have used and replied
- // to them all already.
+ // Erase all exception message as we should have used and replied to them all
+ // already.
m_exception_messages.clear();
return error;
}
@@ -1292,8 +1286,8 @@ Status NativeProcessDarwin::ResumeTask() {
"0x%4.4x",
__FUNCTION__, m_task);
- // Get the BasicInfo struct to verify that we're suspended before we try
- // to resume the task.
+ // Get the BasicInfo struct to verify that we're suspended before we try to
+ // resume the task.
struct task_basic_info task_info;
error = GetTaskBasicInfo(m_task, &task_info);
if (error.Fail()) {
@@ -1304,9 +1298,8 @@ Status NativeProcessDarwin::ResumeTask() {
return error;
}
- // task_resume isn't counted like task_suspend calls are, so if the
- // task is not suspended, don't try and resume it since it is already
- // running
+ // task_resume isn't counted like task_suspend calls are, so if the task is
+ // not suspended, don't try and resume it since it is already running
if (task_info.suspend_count > 0) {
auto mach_err = ::task_resume(m_task);
error.SetError(mach_err, eErrorTypeMachKernel);
diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.h b/source/Plugins/Process/Darwin/NativeProcessDarwin.h
index 649280c17a8f..0b186fd7d80c 100644
--- a/source/Plugins/Process/Darwin/NativeProcessDarwin.h
+++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.h
@@ -43,10 +43,10 @@ class Scalar;
namespace process_darwin {
/// @class NativeProcessDarwin
-/// @brief Manages communication with the inferior (debugee) process.
+/// Manages communication with the inferior (debugee) process.
///
-/// Upon construction, this class prepares and launches an inferior
-/// process for debugging.
+/// Upon construction, this class prepares and launches an inferior process
+/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
class NativeProcessDarwin : public NativeProcessProtocol {
@@ -205,10 +205,10 @@ private:
// -----------------------------------------------------------------
/// Finalize the launch.
///
- /// This method associates the NativeProcessDarwin instance with
- /// the host process that was just launched. It peforms actions
- /// like attaching a listener to the inferior exception port,
- /// ptracing the process, and the like.
+ /// This method associates the NativeProcessDarwin instance with the host
+ /// process that was just launched. It peforms actions like attaching a
+ /// listener to the inferior exception port, ptracing the process, and the
+ /// like.
///
/// @param[in] launch_flavor
/// The launch flavor that was used to launch the process.
@@ -263,8 +263,8 @@ private:
task_t TaskPortForProcessID(Status &error, bool force = false) const;
- /// Attaches to an existing process. Forms the
- /// implementation of Process::DoAttach.
+ /// Attaches to an existing process. Forms the implementation of
+ /// Process::DoAttach.
void AttachToInferior(MainLoop &mainloop, lldb::pid_t pid, Status &error);
::pid_t Attach(lldb::pid_t pid, Status &error);
@@ -323,8 +323,8 @@ private:
Status GetSignalInfo(lldb::tid_t tid, void *siginfo);
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
- /// corresponding to the given thread ID to the memory pointed to
- /// by @p message.
+ /// corresponding to the given thread ID to the memory pointed to by @p
+ /// message.
Status GetEventMessage(lldb::tid_t tid, unsigned long *message);
void NotifyThreadDeath(lldb::tid_t tid);
diff --git a/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp b/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
index 07398ab7b678..521c6d5c8fd0 100644
--- a/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
+++ b/source/Plugins/Process/Darwin/NativeThreadDarwin.cpp
@@ -30,8 +30,8 @@ uint64_t NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID(
(thread_info_t)&tident, &tident_count);
if (mach_err != KERN_SUCCESS) {
// When we fail to get thread info for the supposed port, assume it is
- // really a globally unique thread id already, or return the best thing
- // we can, which is the thread port.
+ // really a globally unique thread id already, or return the best thing we
+ // can, which is the thread port.
return mach_port_id;
}
return tident.thread_id;
@@ -47,9 +47,9 @@ NativeThreadDarwin::NativeThreadDarwin(NativeProcessDarwin *process,
bool NativeThreadDarwin::GetIdentifierInfo() {
// Don't try to get the thread info once and cache it for the life of the
- // thread. It changes over time, for instance
- // if the thread name changes, then the thread_handle also changes... So you
- // have to refetch it every time.
+ // thread. It changes over time, for instance if the thread name changes,
+ // then the thread_handle also changes... So you have to refetch it every
+ // time.
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
kern_return_t kret = ::thread_info(m_mach_thread_port, THREAD_IDENTIFIER_INFO,
(thread_info_t)&m_ident_info, &count);
@@ -137,16 +137,16 @@ bool NativeThreadDarwin::NotifyException(MachException::Data &exc) {
// TODO implement this.
#if 0
// Allow the arch specific protocol to process (MachException::Data &)exc
- // first before possible reassignment of m_stop_exception with exc.
- // See also MachThread::GetStopException().
+ // first before possible reassignment of m_stop_exception with exc. See
+ // also MachThread::GetStopException().
bool handled = m_arch_ap->NotifyException(exc);
if (m_stop_exception.IsValid())
{
// We may have more than one exception for a thread, but we need to
- // only remember the one that we will say is the reason we stopped.
- // We may have been single stepping and also gotten a signal exception,
- // so just remember the most pertinent one.
+ // only remember the one that we will say is the reason we stopped. We
+ // may have been single stepping and also gotten a signal exception, so
+ // just remember the most pertinent one.
if (m_stop_exception.IsBreakpoint())
m_stop_exception = exc;
}
@@ -170,8 +170,8 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
if (bp)
{
- // This thread is sitting at a breakpoint, ask the breakpoint
- // if we should be stopping here.
+ // This thread is sitting at a breakpoint, ask the breakpoint if we
+ // should be stopping here.
return true;
}
else
@@ -181,11 +181,10 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
step_more = true;
return false;
}
- // The thread state is used to let us know what the thread was
- // trying to do. MachThread::ThreadWillResume() will set the
- // thread state to various values depending if the thread was
- // the current thread and if it was to be single stepped, or
- // resumed.
+ // The thread state is used to let us know what the thread was trying
+ // to do. MachThread::ThreadWillResume() will set the thread state to
+ // various values depending if the thread was the current thread and if
+ // it was to be single stepped, or resumed.
if (GetState() == eStateRunning)
{
// If our state is running, then we should continue as we are in
@@ -194,8 +193,7 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
}
else
{
- // Stop if we have any kind of valid exception for this
- // thread.
+ // Stop if we have any kind of valid exception for this thread.
if (GetStopException().IsValid())
return true;
}
@@ -209,17 +207,17 @@ bool NativeThreadDarwin::ShouldStop(bool &step_more) const {
void NativeThreadDarwin::ThreadDidStop() {
// TODO implement this.
#if 0
- // This thread has existed prior to resuming under debug nub control,
- // and has just been stopped. Do any cleanup that needs to be done
- // after running.
+ // This thread has existed prior to resuming under debug nub control, and
+ // has just been stopped. Do any cleanup that needs to be done after
+ // running.
- // The thread state and breakpoint will still have the same values
- // as they had prior to resuming the thread, so it makes it easy to check
- // if we were trying to step a thread, or we tried to resume while being
- // at a breakpoint.
+ // The thread state and breakpoint will still have the same values as they
+ // had prior to resuming the thread, so it makes it easy to check if we
+ // were trying to step a thread, or we tried to resume while being at a
+ // breakpoint.
- // When this method gets called, the process state is still in the
- // state it was in while running so we can act accordingly.
+ // When this method gets called, the process state is still in the state it
+ // was in while running so we can act accordingly.
m_arch_ap->ThreadDidStop();
diff --git a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
index 7d44adeec375..4ff662e42097 100644
--- a/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
+++ b/source/Plugins/Process/Darwin/NativeThreadListDarwin.cpp
@@ -308,8 +308,8 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
__FUNCTION__, process.GetID(), update, process.GetStopID());
if (process.GetStopID() == 0) {
- // On our first stop, we'll record details like 32/64 bitness and
- // select the proper architecture implementation.
+ // On our first stop, we'll record details like 32/64 bitness and select
+ // the proper architecture implementation.
//
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)process.GetID()};
@@ -358,9 +358,9 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
if (thread_list_count > 0) {
collection currThreads;
size_t idx;
- // Iterator through the current thread list and see which threads
- // we already have in our list (keep them), which ones we don't
- // (add them), and which ones are not around anymore (remove them).
+ // Iterator through the current thread list and see which threads we
+ // already have in our list (keep them), which ones we don't (add them),
+ // and which ones are not around anymore (remove them).
for (idx = 0; idx < thread_list_count; ++idx) {
// Get the Mach thread port.
const ::thread_t mach_port_num = thread_list[idx];
@@ -373,18 +373,18 @@ uint32_t NativeThreadListDarwin::UpdateThreadList(NativeProcessDarwin &process,
// Retrieve the thread if it exists.
auto thread_sp = GetThreadByID(unique_thread_id);
if (thread_sp) {
- // We are already tracking it. Keep the existing native
- // thread instance.
+ // We are already tracking it. Keep the existing native thread
+ // instance.
currThreads.push_back(thread_sp);
} else {
- // We don't have a native thread instance for this thread.
- // Create it now.
+ // We don't have a native thread instance for this thread. Create it
+ // now.
thread_sp.reset(new NativeThreadDarwin(
&process, m_is_64_bit, unique_thread_id, mach_port_num));
- // Add the new thread regardless of its is user ready state.
- // Make sure the thread is ready to be displayed and shown
- // to users before we add this thread to our list...
+ // Add the new thread regardless of its is user ready state. Make
+ // sure the thread is ready to be displayed and shown to users before
+ // we add this thread to our list...
if (thread_sp->IsUserReady()) {
if (new_threads)
new_threads->push_back(thread_sp);
@@ -417,9 +417,9 @@ NativeThreadListDarwin::CurrentThread (MachThreadSP& thread_sp)
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
if (m_current_thread.get() == NULL)
{
- // Figure out which thread is going to be our current thread.
- // This is currently done by finding the first thread in the list
- // that has a valid exception.
+ // Figure out which thread is going to be our current thread. This is
+ // currently done by finding the first thread in the list that has a
+ // valid exception.
const size_t num_threads = m_threads.size();
for (uint32_t idx = 0; idx < num_threads; ++idx)
{
@@ -455,8 +455,8 @@ void NativeThreadListDarwin::ProcessWillResume(
NativeProcessDarwin &process, const ResumeActionList &thread_actions) {
std::lock_guard<std::recursive_mutex> locker(m_threads_mutex);
- // Update our thread list, because sometimes libdispatch or the kernel
- // will spawn threads while a task is suspended.
+ // Update our thread list, because sometimes libdispatch or the kernel will
+ // spawn threads while a task is suspended.
NativeThreadListDarwin::collection new_threads;
// TODO implement this.
@@ -489,7 +489,8 @@ void NativeThreadListDarwin::ProcessWillResume(
#if 0
DNBThreadResumeAction resume_new_threads = { -1U, eStateRunning, 0, INVALID_NUB_ADDRESS };
- // If we are planning to run only one thread, any new threads should be suspended.
+ // If we are planning to run only one thread, any new threads should be
+ // suspended.
if (run_one_thread)
resume_new_threads.state = eStateSuspended;
@@ -549,11 +550,11 @@ uint32_t NativeThreadListDarwin::ProcessDidStop(NativeProcessDarwin &process) {
}
//----------------------------------------------------------------------
-// Check each thread in our thread list to see if we should notify our
-// client of the current halt in execution.
+// Check each thread in our thread list to see if we should notify our client
+// of the current halt in execution.
//
-// Breakpoints can have callback functions associated with them than
-// can return true to stop, or false to continue executing the inferior.
+// Breakpoints can have callback functions associated with them than can return
+// true to stop, or false to continue executing the inferior.
//
// RETURNS
// true if we should stop and notify our clients
@@ -607,8 +608,9 @@ NativeThreadListDarwin::DisableHardwareBreakpoint (const DNBBreakpoint* bp) cons
return false;
}
-// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() -> MachProcess::EnableWatchpoint()
-// -> NativeThreadListDarwin::EnableHardwareWatchpoint().
+// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() ->
+// MachProcess::EnableWatchpoint() ->
+// NativeThreadListDarwin::EnableHardwareWatchpoint().
uint32_t
NativeThreadListDarwin::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const
{
@@ -617,14 +619,16 @@ NativeThreadListDarwin::EnableHardwareWatchpoint (const DNBBreakpoint* wp) const
{
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
const size_t num_threads = m_threads.size();
- // On Mac OS X we have to prime the control registers for new threads. We do this
- // using the control register data for the first thread, for lack of a better way of choosing.
+ // On Mac OS X we have to prime the control registers for new threads.
+ // We do this using the control register data for the first thread, for
+ // lack of a better way of choosing.
bool also_set_on_task = true;
for (uint32_t idx = 0; idx < num_threads; ++idx)
{
if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(wp, also_set_on_task)) == INVALID_NUB_HW_INDEX)
{
- // We know that idx failed for some reason. Let's rollback the transaction for [0, idx).
+ // We know that idx failed for some reason. Let's rollback the
+ // transaction for [0, idx).
for (uint32_t i = 0; i < idx; ++i)
m_threads[i]->RollbackTransForHWP();
return INVALID_NUB_HW_INDEX;
@@ -647,14 +651,16 @@ NativeThreadListDarwin::DisableHardwareWatchpoint (const DNBBreakpoint* wp) cons
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
const size_t num_threads = m_threads.size();
- // On Mac OS X we have to prime the control registers for new threads. We do this
- // using the control register data for the first thread, for lack of a better way of choosing.
+ // On Mac OS X we have to prime the control registers for new threads.
+ // We do this using the control register data for the first thread, for
+ // lack of a better way of choosing.
bool also_set_on_task = true;
for (uint32_t idx = 0; idx < num_threads; ++idx)
{
if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task))
{
- // We know that idx failed for some reason. Let's rollback the transaction for [0, idx).
+ // We know that idx failed for some reason. Let's rollback the
+ // transaction for [0, idx).
for (uint32_t i = 0; i < idx; ++i)
m_threads[i]->RollbackTransForHWP();
return false;
@@ -675,7 +681,8 @@ NativeThreadListDarwin::NumSupportedHardwareWatchpoints () const
{
PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex);
const size_t num_threads = m_threads.size();
- // Use an arbitrary thread to retrieve the number of supported hardware watchpoints.
+ // Use an arbitrary thread to retrieve the number of supported hardware
+ // watchpoints.
if (num_threads)
return m_threads[0]->NumSupportedHardwareWatchpoints();
return 0;
diff --git a/source/Plugins/Process/FreeBSD/CMakeLists.txt b/source/Plugins/Process/FreeBSD/CMakeLists.txt
index 63855992d708..c8301f350e07 100644
--- a/source/Plugins/Process/FreeBSD/CMakeLists.txt
+++ b/source/Plugins/Process/FreeBSD/CMakeLists.txt
@@ -1,7 +1,3 @@
-include_directories(.)
-include_directories(../POSIX)
-include_directories(../Utility)
-
add_lldb_library(lldbPluginProcessFreeBSD PLUGIN
ProcessFreeBSD.cpp
FreeBSDThread.cpp
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
index e6557c2d58e0..3576a7f26f86 100644
--- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -57,7 +57,7 @@ using namespace lldb_private;
FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
: Thread(process, tid), m_frame_ap(), m_breakpoint(),
- m_thread_name_valid(false), m_thread_name(), m_posix_thread(NULL) {
+ m_thread_name_valid(false), m_thread_name(), m_posix_thread(nullptr) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
LLDB_LOGV(log, "tid = {0}", tid);
@@ -69,15 +69,15 @@ FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++) {
lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
if (wp.get() && wp->IsEnabled()) {
- // This watchpoint as been enabled; obviously this "new" thread
- // has been created since that watchpoint was enabled. Since
- // the POSIXBreakpointProtocol has yet to be initialized, its
- // m_watchpoints_initialized member will be FALSE. Attempting to
- // read the debug status register to determine if a watchpoint
- // has been hit would result in the zeroing of that register.
- // Since the active debug registers would have been cloned when
- // this thread was created, simply force the m_watchpoints_initized
- // member to TRUE and avoid resetting dr6 and dr7.
+ // This watchpoint as been enabled; obviously this "new" thread has been
+ // created since that watchpoint was enabled. Since the
+ // POSIXBreakpointProtocol has yet to be initialized, its
+ // m_watchpoints_initialized member will be FALSE. Attempting to read
+ // the debug status register to determine if a watchpoint has been hit
+ // would result in the zeroing of that register. Since the active debug
+ // registers would have been cloned when this thread was created, simply
+ // force the m_watchpoints_initized member to TRUE and avoid resetting
+ // dr6 and dr7.
GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
}
}
@@ -98,16 +98,15 @@ void FreeBSDThread::RefreshStateAfterStop() {
// context by the time this function gets called. The KDPRegisterContext
// class has been made smart enough to detect when it needs to invalidate
// which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
- // if (StateIsStoppedState(GetState())
+ // register supply functions where they check the process stop ID and do the
+ // right thing. if (StateIsStoppedState(GetState())
{
const bool force = false;
GetRegisterContext()->InvalidateIfNeeded(force);
}
}
-const char *FreeBSDThread::GetInfo() { return NULL; }
+const char *FreeBSDThread::GetInfo() { return nullptr; }
void FreeBSDThread::SetName(const char *name) {
m_thread_name_valid = (name && name[0]);
@@ -158,15 +157,15 @@ const char *FreeBSDThread::GetName() {
}
if (m_thread_name.empty())
- return NULL;
+ return nullptr;
return m_thread_name.c_str();
}
lldb::RegisterContextSP FreeBSDThread::GetRegisterContext() {
if (!m_reg_context_sp) {
- m_posix_thread = NULL;
+ m_posix_thread = nullptr;
- RegisterInfoInterface *reg_interface = NULL;
+ RegisterInfoInterface *reg_interface = nullptr;
const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD);
@@ -282,7 +281,7 @@ bool FreeBSDThread::CalculateStopInfo() {
}
Unwind *FreeBSDThread::GetUnwinder() {
- if (m_unwinder_ap.get() == NULL)
+ if (!m_unwinder_ap)
m_unwinder_ap.reset(new UnwindLLDB(*this));
return m_unwinder_ap.get();
@@ -469,22 +468,19 @@ void FreeBSDThread::BreakNotify(const ProcessMessage &message) {
GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
// If the breakpoint is for this thread, then we'll report the hit, but if it
- // is for another thread,
- // we create a stop reason with should_stop=false. If there is no breakpoint
- // location, then report
- // an invalid stop reason. We don't need to worry about stepping over the
- // breakpoint here, that will
- // be taken care of when the thread resumes and notices that there's a
+ // is for another thread, we create a stop reason with should_stop=false. If
+ // there is no breakpoint location, then report an invalid stop reason. We
+ // don't need to worry about stepping over the breakpoint here, that will be
+ // taken care of when the thread resumes and notices that there's a
// breakpoint under the pc.
if (bp_site) {
lldb::break_id_t bp_id = bp_site->GetID();
// If we have an operating system plug-in, we might have set a thread
- // specific breakpoint using the
- // operating system thread ID, so we can't make any assumptions about the
- // thread ID so we must always
- // report the breakpoint regardless of the thread.
+ // specific breakpoint using the operating system thread ID, so we can't
+ // make any assumptions about the thread ID so we must always report the
+ // breakpoint regardless of the thread.
if (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != NULL)
+ GetProcess()->GetOperatingSystem() != nullptr)
SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
else {
const bool should_stop = false;
@@ -541,15 +537,14 @@ void FreeBSDThread::TraceNotify(const ProcessMessage &message) {
lldb::BreakpointSiteSP bp_site(
GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
- // If the current pc is a breakpoint site then set the StopInfo to Breakpoint.
- // Otherwise, set the StopInfo to Watchpoint or Trace.
- // If we have an operating system plug-in, we might have set a thread specific
- // breakpoint using the
- // operating system thread ID, so we can't make any assumptions about the
- // thread ID so we must always
- // report the breakpoint regardless of the thread.
+ // If the current pc is a breakpoint site then set the StopInfo to
+ // Breakpoint. Otherwise, set the StopInfo to Watchpoint or Trace. If we have
+ // an operating system plug-in, we might have set a thread specific
+ // breakpoint using the operating system thread ID, so we can't make any
+ // assumptions about the thread ID so we must always report the breakpoint
+ // regardless of the thread.
if (bp_site && (bp_site->ValidForThisThread(this) ||
- GetProcess()->GetOperatingSystem() != NULL))
+ GetProcess()->GetOperatingSystem() != nullptr))
SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(
*this, bp_site->GetID()));
else {
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
index 72e846459552..c93cc4fbfd73 100644
--- a/source/Plugins/Process/FreeBSD/FreeBSDThread.h
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
@@ -24,7 +24,7 @@ class POSIXBreakpointProtocol;
//------------------------------------------------------------------------------
// @class FreeBSDThread
-// @brief Abstraction of a FreeBSD thread.
+// Abstraction of a FreeBSD thread.
class FreeBSDThread : public lldb_private::Thread {
public:
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
index 96861852b38e..ff3693107170 100644
--- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
+++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
@@ -17,7 +17,7 @@
//===----------------------------------------------------------------------===//
/// @class POSIXStopInfo
-/// @brief Simple base class for all POSIX-specific StopInfo objects.
+/// Simple base class for all POSIX-specific StopInfo objects.
///
class POSIXStopInfo : public lldb_private::StopInfo {
public:
@@ -27,7 +27,7 @@ public:
//===----------------------------------------------------------------------===//
/// @class POSIXLimboStopInfo
-/// @brief Represents the stop state of a process ready to exit.
+/// Represents the stop state of a process ready to exit.
///
class POSIXLimboStopInfo : public POSIXStopInfo {
public:
@@ -46,7 +46,7 @@ public:
//===----------------------------------------------------------------------===//
/// @class POSIXNewThreadStopInfo
-/// @brief Represents the stop state of process when a new thread is spawned.
+/// Represents the stop state of process when a new thread is spawned.
///
class POSIXNewThreadStopInfo : public POSIXStopInfo {
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index 7a937db49be0..fa0bcea8f6bd 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -357,10 +357,10 @@ ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
if (file_action && file_action->GetAction() == FileAction::eFileActionOpen) {
file_spec = file_action->GetFileSpec();
- // By default the stdio paths passed in will be pseudo-terminal
- // (/dev/pts). If so, convert to using a different default path
- // instead to redirect I/O to the debugger console. This should
- // also handle user overrides to /dev/null or a different file.
+ // By default the stdio paths passed in will be pseudo-terminal (/dev/pts).
+ // If so, convert to using a different default path instead to redirect I/O
+ // to the debugger console. This should also handle user overrides to
+ // /dev/null or a different file.
if (!file_spec || file_spec == dbg_pts_file_spec)
file_spec = default_file_spec;
}
@@ -407,9 +407,8 @@ Status ProcessFreeBSD::DoLaunch(Module *module,
m_monitor = new ProcessMonitor(
this, module, launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
- stdin_file_spec, stdout_file_spec, stderr_file_spec, working_dir,
- launch_info, error);
+ launch_info.GetEnvironment(), stdin_file_spec, stdout_file_spec,
+ stderr_file_spec, working_dir, launch_info, error);
m_module = module;
@@ -656,19 +655,19 @@ ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite *bp_site) {
break;
case llvm::Triple::arm: {
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
- // but the linux kernel does otherwise.
+ // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
+ // linux kernel does otherwise.
static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
- AddressClass addr_class = eAddressClassUnknown;
+ AddressClass addr_class = AddressClass::eUnknown;
if (bp_loc_sp)
addr_class = bp_loc_sp->GetAddress().GetAddressClass();
- if (addr_class == eAddressClassCodeAlternateISA ||
- (addr_class == eAddressClassUnknown &&
+ if (addr_class == AddressClass::eCodeAlternateISA ||
+ (addr_class == AddressClass::eUnknown &&
bp_loc_sp->GetAddress().GetOffset() & 1)) {
opcode = g_thumb_breakpoint_opcode;
opcode_size = sizeof(g_thumb_breakpoint_opcode);
@@ -745,8 +744,8 @@ Status ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) {
wp->SetEnabled(true, notify);
return error;
} else {
- // Watchpoint enabling failed on at least one
- // of the threads so roll back all of them
+ // Watchpoint enabling failed on at least one of the threads so roll
+ // back all of them
DisableWatchpoint(wp, false);
error.SetErrorString("Setting hardware watchpoint failed");
}
@@ -813,8 +812,8 @@ Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) {
Status ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
Status error = GetWatchpointSupportInfo(num);
- // Watchpoints trigger and halt the inferior after
- // the corresponding instruction has been executed.
+ // Watchpoints trigger and halt the inferior after the corresponding
+ // instruction has been executed.
after = true;
return error;
}
@@ -1077,8 +1076,8 @@ Status ProcessFreeBSD::SetupSoftwareSingleStepping(lldb::tid_t tid) {
"Emulation was successful but PC wasn't updated");
next_pc = pc_it->second.GetAsUInt64();
} else if (pc_it == baton.m_register_values.end()) {
- // Emulate instruction failed and it haven't changed PC. Advance PC
- // with the size of the current opcode because the emulation of all
+ // Emulate instruction failed and it haven't changed PC. Advance PC with
+ // the size of the current opcode because the emulation of all
// PC modifying instruction should be successful. The failure most
// likely caused by a not supported instruction which don't modify PC.
next_pc =
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index bd06fa25f0a0..51fdf2e5ef33 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -38,15 +38,11 @@
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
-extern "C" {
-extern char **environ;
-}
-
using namespace lldb;
using namespace lldb_private;
-// We disable the tracing of ptrace calls for integration builds to
-// avoid the additional indirection and checks.
+// We disable the tracing of ptrace calls for integration builds to avoid the
+// additional indirection and checks.
#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
// Wrapper for ptrace to catch errors and log calls.
@@ -65,9 +61,8 @@ const char *Get_PT_IO_OP(int op) {
}
}
-// Wrapper for ptrace to catch errors and log calls.
-// Note that ptrace sets errno on error because -1 is reserved as a valid
-// result.
+// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets
+// errno on error because -1 is reserved as a valid result.
extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
const char *reqName, const char *file, int line) {
long int result;
@@ -134,8 +129,8 @@ extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
return result;
}
-// Wrapper for ptrace when logging is not required.
-// Sets errno to 0 prior to calling ptrace.
+// Wrapper for ptrace when logging is not required. Sets errno to 0 prior to
+// calling ptrace.
extern long PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data) {
long result = 0;
errno = 0;
@@ -163,8 +158,10 @@ static size_t DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf,
pi_desc.piod_addr = buf;
pi_desc.piod_len = size;
- if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
+ if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) {
error.SetErrorToErrno();
+ return 0;
+ }
return pi_desc.piod_len;
}
@@ -177,8 +174,10 @@ static size_t DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr,
pi_desc.piod_addr = (void *)buf;
pi_desc.piod_len = size;
- if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
+ if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0) {
error.SetErrorToErrno();
+ return 0;
+ }
return pi_desc.piod_len;
}
@@ -202,15 +201,16 @@ static bool EnsureFDFlags(int fd, int flags, Status &error) {
//------------------------------------------------------------------------------
/// @class Operation
-/// @brief Represents a ProcessMonitor operation.
+/// Represents a ProcessMonitor operation.
///
-/// Under FreeBSD, it is not possible to ptrace() from any other thread but the
-/// one that spawned or attached to the process from the start. Therefore, when
-/// a ProcessMonitor is asked to deliver or change the state of an inferior
-/// process the operation must be "funneled" to a specific thread to perform the
-/// task. The Operation class provides an abstract base for all services the
-/// ProcessMonitor must perform via the single virtual function Execute, thus
-/// encapsulating the code that needs to run in the privileged context.
+/// Under FreeBSD, it is not possible to ptrace() from any other thread but
+/// the one that spawned or attached to the process from the start.
+/// Therefore, when a ProcessMonitor is asked to deliver or change the state
+/// of an inferior process the operation must be "funneled" to a specific
+/// thread to perform the task. The Operation class provides an abstract base
+/// for all services the ProcessMonitor must perform via the single virtual
+/// function Execute, thus encapsulating the code that needs to run in the
+/// privileged context.
class Operation {
public:
virtual ~Operation() {}
@@ -219,7 +219,7 @@ public:
//------------------------------------------------------------------------------
/// @class ReadOperation
-/// @brief Implements ProcessMonitor::ReadMemory.
+/// Implements ProcessMonitor::ReadMemory.
class ReadOperation : public Operation {
public:
ReadOperation(lldb::addr_t addr, void *buff, size_t size, Status &error,
@@ -245,7 +245,7 @@ void ReadOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteOperation
-/// @brief Implements ProcessMonitor::WriteMemory.
+/// Implements ProcessMonitor::WriteMemory.
class WriteOperation : public Operation {
public:
WriteOperation(lldb::addr_t addr, const void *buff, size_t size,
@@ -271,7 +271,7 @@ void WriteOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadRegOperation
-/// @brief Implements ProcessMonitor::ReadRegisterValue.
+/// Implements ProcessMonitor::ReadRegisterValue.
class ReadRegOperation : public Operation {
public:
ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
@@ -311,7 +311,7 @@ void ReadRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteRegOperation
-/// @brief Implements ProcessMonitor::WriteRegisterValue.
+/// Implements ProcessMonitor::WriteRegisterValue.
class WriteRegOperation : public Operation {
public:
WriteRegOperation(lldb::tid_t tid, unsigned offset,
@@ -344,7 +344,7 @@ void WriteRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadDebugRegOperation
-/// @brief Implements ProcessMonitor::ReadDebugRegisterValue.
+/// Implements ProcessMonitor::ReadDebugRegisterValue.
class ReadDebugRegOperation : public Operation {
public:
ReadDebugRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
@@ -379,7 +379,7 @@ void ReadDebugRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteDebugRegOperation
-/// @brief Implements ProcessMonitor::WriteDebugRegisterValue.
+/// Implements ProcessMonitor::WriteDebugRegisterValue.
class WriteDebugRegOperation : public Operation {
public:
WriteDebugRegOperation(lldb::tid_t tid, unsigned offset,
@@ -412,7 +412,7 @@ void WriteDebugRegOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadGPROperation
-/// @brief Implements ProcessMonitor::ReadGPR.
+/// Implements ProcessMonitor::ReadGPR.
class ReadGPROperation : public Operation {
public:
ReadGPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -439,7 +439,7 @@ void ReadGPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ReadFPROperation
-/// @brief Implements ProcessMonitor::ReadFPR.
+/// Implements ProcessMonitor::ReadFPR.
class ReadFPROperation : public Operation {
public:
ReadFPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -462,7 +462,7 @@ void ReadFPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteGPROperation
-/// @brief Implements ProcessMonitor::WriteGPR.
+/// Implements ProcessMonitor::WriteGPR.
class WriteGPROperation : public Operation {
public:
WriteGPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -485,7 +485,7 @@ void WriteGPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class WriteFPROperation
-/// @brief Implements ProcessMonitor::WriteFPR.
+/// Implements ProcessMonitor::WriteFPR.
class WriteFPROperation : public Operation {
public:
WriteFPROperation(lldb::tid_t tid, void *buf, bool &result)
@@ -508,7 +508,7 @@ void WriteFPROperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ResumeOperation
-/// @brief Implements ProcessMonitor::Resume.
+/// Implements ProcessMonitor::Resume.
class ResumeOperation : public Operation {
public:
ResumeOperation(uint32_t signo, bool &result)
@@ -539,7 +539,7 @@ void ResumeOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class SingleStepOperation
-/// @brief Implements ProcessMonitor::SingleStep.
+/// Implements ProcessMonitor::SingleStep.
class SingleStepOperation : public Operation {
public:
SingleStepOperation(uint32_t signo, bool &result)
@@ -567,7 +567,7 @@ void SingleStepOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class LwpInfoOperation
-/// @brief Implements ProcessMonitor::GetLwpInfo.
+/// Implements ProcessMonitor::GetLwpInfo.
class LwpInfoOperation : public Operation {
public:
LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
@@ -596,7 +596,7 @@ void LwpInfoOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class ThreadSuspendOperation
-/// @brief Implements ProcessMonitor::ThreadSuspend.
+/// Implements ProcessMonitor::ThreadSuspend.
class ThreadSuspendOperation : public Operation {
public:
ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result)
@@ -616,7 +616,7 @@ void ThreadSuspendOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class EventMessageOperation
-/// @brief Implements ProcessMonitor::GetEventMessage.
+/// Implements ProcessMonitor::GetEventMessage.
class EventMessageOperation : public Operation {
public:
EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)
@@ -646,7 +646,7 @@ void EventMessageOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class KillOperation
-/// @brief Implements ProcessMonitor::Kill.
+/// Implements ProcessMonitor::Kill.
class KillOperation : public Operation {
public:
KillOperation(bool &result) : m_result(result) {}
@@ -668,7 +668,7 @@ void KillOperation::Execute(ProcessMonitor *monitor) {
//------------------------------------------------------------------------------
/// @class DetachOperation
-/// @brief Implements ProcessMonitor::Detach.
+/// Implements ProcessMonitor::Detach.
class DetachOperation : public Operation {
public:
DetachOperation(Status &result) : m_error(result) {}
@@ -695,13 +695,14 @@ ProcessMonitor::OperationArgs::~OperationArgs() { sem_destroy(&m_semaphore); }
ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
lldb_private::Module *module,
- char const **argv, char const **envp,
+ char const **argv, Environment env,
const FileSpec &stdin_file_spec,
const FileSpec &stdout_file_spec,
const FileSpec &stderr_file_spec,
const FileSpec &working_dir)
- : OperationArgs(monitor), m_module(module), m_argv(argv), m_envp(envp),
- m_stdin_file_spec(stdin_file_spec), m_stdout_file_spec(stdout_file_spec),
+ : OperationArgs(monitor), m_module(module), m_argv(argv),
+ m_env(std::move(env)), m_stdin_file_spec(stdin_file_spec),
+ m_stdout_file_spec(stdout_file_spec),
m_stderr_file_spec(stderr_file_spec), m_working_dir(working_dir) {}
ProcessMonitor::LaunchArgs::~LaunchArgs() {}
@@ -714,11 +715,10 @@ ProcessMonitor::AttachArgs::~AttachArgs() {}
//------------------------------------------------------------------------------
/// The basic design of the ProcessMonitor is built around two threads.
///
-/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking
-/// for changes in the debugee state. When a change is detected a
+/// One thread (@see SignalThread) simply blocks on a call to waitpid()
+/// looking for changes in the debugee state. When a change is detected a
/// ProcessMessage is sent to the associated ProcessFreeBSD instance. This
-/// thread
-/// "drives" state changes in the debugger.
+/// thread "drives" state changes in the debugger.
///
/// The second thread (@see OperationThread) is responsible for two things 1)
/// launching or attaching to the inferior process, and then 2) servicing
@@ -726,7 +726,7 @@ ProcessMonitor::AttachArgs::~AttachArgs() {}
/// on the Operation class for more info as to why this is needed.
ProcessMonitor::ProcessMonitor(
ProcessFreeBSD *process, Module *module, const char *argv[],
- const char *envp[], const FileSpec &stdin_file_spec,
+ Environment env, const FileSpec &stdin_file_spec,
const FileSpec &stdout_file_spec, const FileSpec &stderr_file_spec,
const FileSpec &working_dir,
const lldb_private::ProcessLaunchInfo & /* launch_info */,
@@ -736,7 +736,7 @@ ProcessMonitor::ProcessMonitor(
using namespace std::placeholders;
std::unique_ptr<LaunchArgs> args(
- new LaunchArgs(this, module, argv, envp, stdin_file_spec,
+ new LaunchArgs(this, module, argv, std::move(env), stdin_file_spec,
stdout_file_spec, stderr_file_spec, working_dir));
sem_init(&m_operation_pending, 0, 0);
@@ -837,7 +837,6 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
ProcessMonitor *monitor = args->m_monitor;
ProcessFreeBSD &process = monitor->GetProcess();
const char **argv = args->m_argv;
- const char **envp = args->m_envp;
const FileSpec &stdin_file_spec = args->m_stdin_file_spec;
const FileSpec &stdout_file_spec = args->m_stdout_file_spec;
const FileSpec &stderr_file_spec = args->m_stderr_file_spec;
@@ -849,8 +848,8 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
::pid_t pid;
// Propagate the environment if one is not supplied.
- if (envp == NULL || envp[0] == NULL)
- envp = const_cast<const char **>(environ);
+ Environment::Envp envp =
+ (args->m_env.empty() ? Host::GetEnvironment() : args->m_env).getEnvp();
if ((pid = terminal.Fork(err_str, err_len)) == -1) {
args->m_error.SetErrorToGenericError();
@@ -875,9 +874,9 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)
exit(ePtraceFailed);
- // terminal has already dupped the tty descriptors to stdin/out/err.
- // This closes original fd from which they were copied (and avoids
- // leaking descriptors to the debugged process.
+ // terminal has already dupped the tty descriptors to stdin/out/err. This
+ // closes original fd from which they were copied (and avoids leaking
+ // descriptors to the debugged process.
terminal.CloseSlaveFileDescriptor();
// Do not inherit setgid powers.
@@ -908,8 +907,7 @@ bool ProcessMonitor::Launch(LaunchArgs *args) {
exit(eChdirFailed);
// Execute. We should never return.
- execve(argv[0], const_cast<char *const *>(argv),
- const_cast<char *const *>(envp));
+ execve(argv[0], const_cast<char *const *>(argv), envp);
exit(eExecFailed);
}
@@ -1103,9 +1101,9 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
break;
case (SIGTRAP /* | (PTRACE_EVENT_EXIT << 8) */): {
- // The inferior process is about to exit. Maintain the process in a
- // state of "limbo" until we are explicitly commanded to detach,
- // destroy, resume, etc.
+ // The inferior process is about to exit. Maintain the process in a state
+ // of "limbo" until we are explicitly commanded to detach, destroy, resume,
+ // etc.
unsigned long data = 0;
if (!monitor->GetEventMessage(tid, &data))
data = -1;
@@ -1160,8 +1158,8 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// POSIX says that process behaviour is undefined after it ignores a SIGFPE,
- // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
- // kill(2) or raise(3). Similarly for tgkill(2) on FreeBSD.
+ // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2)
+ // or raise(3). Similarly for tgkill(2) on FreeBSD.
//
// IOW, user generated signals never generate what we consider to be a
// "crash".
@@ -1197,8 +1195,8 @@ ProcessMessage ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
} // else; Use atleast si_signo info for other si_code
}
- // Everything else is "normal" and does not require any special action on
- // our part.
+ // Everything else is "normal" and does not require any special action on our
+ // part.
return ProcessMessage::Signal(tid, signo);
}
@@ -1424,14 +1422,14 @@ void ProcessMonitor::StopMonitor() {
}
// FIXME: On Linux, when a new thread is created, we receive to notifications,
-// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the
-// child thread id as additional information, and (2) a SIGSTOP|SI_USER from
-// the new child thread indicating that it has is stopped because we attached.
-// We have no guarantee of the order in which these arrive, but we need both
-// before we are ready to proceed. We currently keep a list of threads which
-// have sent the initial SIGSTOP|SI_USER event. Then when we receive the
-// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not occurred
-// we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
+// (1) a SIGTRAP|PTRACE_EVENT_CLONE from the main process thread with the child
+// thread id as additional information, and (2) a SIGSTOP|SI_USER from the new
+// child thread indicating that it has is stopped because we attached. We have
+// no guarantee of the order in which these arrive, but we need both before we
+// are ready to proceed. We currently keep a list of threads which have sent
+// the initial SIGSTOP|SI_USER event. Then when we receive the
+// SIGTRAP|PTRACE_EVENT_CLONE notification, if the initial stop has not
+// occurred we call ProcessMonitor::WaitForInitialTIDStop() to wait for it.
//
// Right now, the above logic is in ProcessPOSIX, so we need a definition of
// this function in the FreeBSD ProcessMonitor implementation even if it isn't
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 0963453a31b1..1d3e2d746fa9 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -32,10 +32,10 @@ class ProcessFreeBSD;
class Operation;
/// @class ProcessMonitor
-/// @brief Manages communication with the inferior (debugee) process.
+/// Manages communication with the inferior (debugee) process.
///
-/// Upon construction, this class prepares and launches an inferior process for
-/// debugging.
+/// Upon construction, this class prepares and launches an inferior process
+/// for debugging.
///
/// Changes in the inferior process state are propagated to the associated
/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the
@@ -48,7 +48,7 @@ public:
/// Launches an inferior process ready for debugging. Forms the
/// implementation of Process::DoLaunch.
ProcessMonitor(ProcessFreeBSD *process, lldb_private::Module *module,
- char const *argv[], char const *envp[],
+ char const *argv[], lldb_private::Environment env,
const lldb_private::FileSpec &stdin_file_spec,
const lldb_private::FileSpec &stdout_file_spec,
const lldb_private::FileSpec &stderr_file_spec,
@@ -74,8 +74,7 @@ public:
/// standard error of this debugee. Even if stderr and stdout were
/// redirected on launch it may still happen that data is available on this
/// descriptor (if the inferior process opens /dev/tty, for example). This
- /// descriptor is
- /// closed after a call to StopMonitor().
+ /// descriptor is closed after a call to StopMonitor().
///
/// If this monitor was attached to an existing process this method returns
/// -1.
@@ -95,8 +94,8 @@ public:
size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
lldb_private::Status &error);
- /// Reads the contents from the register identified by the given (architecture
- /// dependent) offset.
+ /// Reads the contents from the register identified by the given
+ /// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
@@ -215,11 +214,11 @@ private:
/// @class LauchArgs
///
- /// @brief Simple structure to pass data to the thread responsible for
- /// launching a child process.
+ /// Simple structure to pass data to the thread responsible for launching a
+ /// child process.
struct LaunchArgs : OperationArgs {
LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module,
- char const **argv, char const **envp,
+ char const **argv, lldb_private::Environment env,
const lldb_private::FileSpec &stdin_file_spec,
const lldb_private::FileSpec &stdout_file_spec,
const lldb_private::FileSpec &stderr_file_spec,
@@ -229,7 +228,7 @@ private:
lldb_private::Module *m_module; // The executable image to launch.
char const **m_argv; // Process arguments.
- char const **m_envp; // Process environment.
+ lldb_private::Environment m_env; // Process environment.
const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty.
const lldb_private::FileSpec
m_stdout_file_spec; // Redirect stdout or empty.
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
index 4ff5121bac13..b1b44e71de46 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
@@ -13,14 +13,14 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-#include "RegisterInfoInterface.h"
+#include "Plugins/Process/Utility/RegisterInfoInterface.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/ArchSpec.h"
//------------------------------------------------------------------------------
/// @class POSIXBreakpointProtocol
///
-/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
+/// Extends RegisterClass with a few virtual operations useful on POSIX.
class POSIXBreakpointProtocol {
public:
POSIXBreakpointProtocol() { m_watchpoints_initialized = false; }
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
index 59d42b9ad72e..8ddc253aea5d 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
@@ -14,7 +14,7 @@
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "RegisterContextPOSIX_arm.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
using namespace lldb_private;
using namespace lldb;
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
index b911ee222015..734167e1fc98 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -130,14 +130,14 @@ bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
bool success = ReadRegister(full_reg, value);
if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
- // one byte to the right.
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned
+ // value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
value.SetUInt64(value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
index bc1d4df89fc8..5cc6cd290629 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -14,7 +14,7 @@
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "RegisterContextPOSIX_powerpc.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
using namespace lldb_private;
using namespace lldb;
@@ -140,8 +140,8 @@ bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
if (success) {
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
index 4608520dba40..7db7f803b371 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -193,14 +193,14 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
bool success = ReadRegister(full_reg, value);
if (success) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
- // one byte to the right.
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned
+ // value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
value.SetUInt64(value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
@@ -221,7 +221,8 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
reg_info->byte_size, byte_order);
if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
- // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+ // Concatenate ymm using the register halves in xmm.bytes and
+ // ymmh.bytes
if (GetFPRType() == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
reg_info->byte_size, byte_order);
@@ -233,11 +234,10 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(
return false;
}
- // Get pointer to m_fpr.fxsave variable and set the data from it.
- // Byte offsets of all registers are calculated wrt 'UserArea' structure.
- // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)}
- // and stores them in 'm_fpr' (of type FPR structure). To extract values of
- // fpu
+ // Get pointer to m_fpr.fxsave variable and set the data from it. Byte
+ // offsets of all registers are calculated wrt 'UserArea' structure. However,
+ // ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)} and stores
+ // them in 'm_fpr' (of type FPR structure). To extract values of fpu
// registers, m_fpr should be read at byte offsets calculated wrt to FPR
// structure.
@@ -299,12 +299,12 @@ bool RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(
return false;
}
} else {
- // Get pointer to m_fpr.fxsave variable and set the data to it.
- // Byte offsets of all registers are calculated wrt 'UserArea' structure.
- // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only
- // fpu
- // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should
- // be written in m_fpr at byte offsets calculated wrt FPR structure.
+ // Get pointer to m_fpr.fxsave variable and set the data to it. Byte
+ // offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
+ // only fpu registers using ptrace(PT_SETFPREGS,..) API. Hence fpu
+ // registers should be written in m_fpr at byte offsets calculated wrt
+ // FPR structure.
// Since, FPR structure is also one of the member of UserArea structure.
// byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt
index 390dbd9ff8bf..b4b4c401a271 100644
--- a/source/Plugins/Process/Linux/CMakeLists.txt
+++ b/source/Plugins/Process/Linux/CMakeLists.txt
@@ -1,7 +1,3 @@
-include_directories(.)
-include_directories(../POSIX)
-include_directories(../Utility)
-
add_lldb_library(lldbPluginProcessLinux PLUGIN
NativeProcessLinux.cpp
NativeRegisterContextLinux.cpp
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 136af361af29..3fb886e1c7a3 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -245,13 +245,15 @@ NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info,
}
LLDB_LOG(log, "inferior started, now in stopped state");
- ArchSpec arch;
- if ((status = ResolveProcessArchitecture(pid, arch)).Fail())
- return status.ToError();
+ ProcessInstanceInfo Info;
+ if (!Host::GetProcessInfo(pid, Info)) {
+ return llvm::make_error<StringError>("Cannot get process architecture",
+ llvm::inconvertibleErrorCode());
+ }
// Set the architecture to the exe architecture.
LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
- arch.GetArchitectureName());
+ Info.GetArchitecture().GetArchitectureName());
status = SetDefaultPtraceOpts(pid);
if (status.Fail()) {
@@ -261,7 +263,7 @@ NativeProcessLinux::Factory::Launch(ProcessLaunchInfo &launch_info,
return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
- arch, mainloop, {pid}));
+ Info.GetArchitecture(), mainloop, {pid}));
}
llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
@@ -272,17 +274,18 @@ NativeProcessLinux::Factory::Attach(
LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
- ArchSpec arch;
- Status status = ResolveProcessArchitecture(pid, arch);
- if (!status.Success())
- return status.ToError();
+ ProcessInstanceInfo Info;
+ if (!Host::GetProcessInfo(pid, Info)) {
+ return llvm::make_error<StringError>("Cannot get process architecture",
+ llvm::inconvertibleErrorCode());
+ }
auto tids_or = NativeProcessLinux::Attach(pid);
if (!tids_or)
return tids_or.takeError();
return std::unique_ptr<NativeProcessLinux>(new NativeProcessLinux(
- pid, -1, native_delegate, arch, mainloop, *tids_or));
+ pid, -1, native_delegate, Info.GetArchitecture(), mainloop, *tids_or));
}
// -----------------------------------------------------------------------------
@@ -334,8 +337,8 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
// Attach to the requested process.
// An attach will cause the thread to stop with a SIGSTOP.
if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) {
- // No such thread. The thread may have exited.
- // More error handling may be needed.
+ // No such thread. The thread may have exited. More error handling
+ // may be needed.
if (status.GetError() == ESRCH) {
it = tids_to_attach.erase(it);
continue;
@@ -345,11 +348,11 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
int wpid =
llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL);
- // Need to use __WALL otherwise we receive an error with errno=ECHLD
- // At this point we should have a thread stopped if waitpid succeeds.
+ // Need to use __WALL otherwise we receive an error with errno=ECHLD At
+ // this point we should have a thread stopped if waitpid succeeds.
if (wpid < 0) {
- // No such thread. The thread may have exited.
- // More error handling may be needed.
+ // No such thread. The thread may have exited. More error handling
+ // may be needed.
if (errno == ESRCH) {
it = tids_to_attach.erase(it);
continue;
@@ -394,8 +397,8 @@ Status NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) {
// appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
ptrace_opts |= PTRACE_O_TRACECLONE;
- // Have the tracer notify us before execve returns
- // (needed to disable legacy SIGTRAP generation)
+ // Have the tracer notify us before execve returns (needed to disable legacy
+ // SIGTRAP generation)
ptrace_opts |= PTRACE_O_TRACEEXEC;
return PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void *)ptrace_opts);
@@ -435,8 +438,8 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
auto thread_sp = GetThreadByID(pid);
if (!thread_sp) {
- // Normally, the only situation when we cannot find the thread is if we have
- // just received a new thread notification. This is indicated by
+ // Normally, the only situation when we cannot find the thread is if we
+ // have just received a new thread notification. This is indicated by
// GetSignalInfo() returning si_code == SI_USER and si_pid == 0
LLDB_LOG(log, "received notification about an unknown tid {0}.", pid);
@@ -468,15 +471,15 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
MonitorSignal(info, *thread_sp, exited);
} else {
if (info_err.GetError() == EINVAL) {
- // This is a group stop reception for this tid.
- // We can reach here if we reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU
- // into the tracee, triggering the group-stop mechanism. Normally
- // receiving these would stop the process, pending a SIGCONT. Simulating
- // this state in a debugger is hard and is generally not needed (one use
- // case is debugging background task being managed by a shell). For
- // general use, it is sufficient to stop the process in a signal-delivery
- // stop which happens before the group stop. This done by MonitorSignal
- // and works correctly for all signals.
+ // This is a group stop reception for this tid. We can reach here if we
+ // reinject SIGSTOP, SIGSTP, SIGTTIN or SIGTTOU into the tracee,
+ // triggering the group-stop mechanism. Normally receiving these would
+ // stop the process, pending a SIGCONT. Simulating this state in a
+ // debugger is hard and is generally not needed (one use case is
+ // debugging background task being managed by a shell). For general use,
+ // it is sufficient to stop the process in a signal-delivery stop which
+ // happens before the group stop. This done by MonitorSignal and works
+ // correctly for all signals.
LLDB_LOG(log,
"received a group stop for pid {0} tid {1}. Transparent "
"handling of group stops not supported, resuming the "
@@ -502,8 +505,8 @@ void NativeProcessLinux::MonitorCallback(lldb::pid_t pid, bool exited,
if (is_main_thread) {
// Notify the delegate - our process is not available but appears to
- // have been killed outside
- // our control. Is eStateExited the right exit state in this case?
+ // have been killed outside our control. Is eStateExited the right
+ // exit state in this case?
SetExitStatus(status, true);
SetState(StateType::eStateExited, true);
} else {
@@ -572,19 +575,14 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
switch (info.si_code) {
// TODO: these two cases are required if we want to support tracing of the
- // inferiors' children. We'd need this to debug a monitor.
- // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
- // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
+ // inferiors' children. We'd need this to debug a monitor. case (SIGTRAP |
+ // (PTRACE_EVENT_FORK << 8)): case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): {
// This is the notification on the parent thread which informs us of new
- // thread
- // creation.
- // We don't want to do anything with the parent thread so we just resume it.
- // In case we
- // want to implement "break on thread creation" functionality, we would need
- // to stop
- // here.
+ // thread creation. We don't want to do anything with the parent thread so
+ // we just resume it. In case we want to implement "break on thread
+ // creation" functionality, we would need to stop here.
unsigned long event_message = 0;
if (GetEventMessage(thread.GetID(), &event_message).Fail()) {
@@ -634,10 +632,10 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
}
case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): {
- // The inferior process or one of its threads is about to exit.
- // We don't want to do anything with the thread so we just resume it. In
- // case we want to implement "break on thread exit" functionality, we would
- // need to stop here.
+ // The inferior process or one of its threads is about to exit. We don't
+ // want to do anything with the thread so we just resume it. In case we
+ // want to implement "break on thread exit" functionality, we would need to
+ // stop here.
unsigned long data = 0;
if (GetEventMessage(thread.GetID(), &data).Fail())
@@ -655,8 +653,8 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
// Due to a kernel bug, we may sometimes get this stop after the inferior
// gets a SIGKILL. This confuses our state tracking logic in
// ResumeThread(), since normally, we should not be receiving any ptrace
- // events while the inferior is stopped. This makes sure that the inferior
- // is resumed and exits normally.
+ // events while the inferior is stopped. This makes sure that the
+ // inferior is resumed and exits normally.
state = eStateRunning;
}
ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER);
@@ -702,8 +700,8 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
case SI_KERNEL:
#if defined __mips__
- // For mips there is no special signal for watchpoint
- // So we check for watchpoint in kernel trap
+ // For mips there is no special signal for watchpoint So we check for
+ // watchpoint in kernel trap
{
// If a watchpoint was hit, report it
uint32_t wp_index;
@@ -779,8 +777,8 @@ void NativeProcessLinux::MonitorWatchpoint(NativeThreadLinux &thread,
LLDB_LOG(log, "received watchpoint event, pid = {0}, wp_index = {1}",
thread.GetID(), wp_index);
- // Mark the thread as stopped at watchpoint.
- // The address is at (lldb::addr_t)info->si_addr if we need it.
+ // Mark the thread as stopped at watchpoint. The address is at
+ // (lldb::addr_t)info->si_addr if we need it.
thread.SetStoppedByWatchpoint(wp_index);
// We need to tell all other running threads before we notify the delegate
@@ -796,8 +794,8 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
// POSIX says that process behaviour is undefined after it ignores a SIGFPE,
- // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
- // kill(2) or raise(3). Similarly for tgkill(2) on Linux.
+ // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a kill(2)
+ // or raise(3). Similarly for tgkill(2) on Linux.
//
// IOW, user generated signals never generate what we consider to be a
// "crash".
@@ -816,22 +814,22 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
// This is a tgkill()-based stop.
LLDB_LOG(log, "pid {0} tid {1}, thread stopped", GetID(), thread.GetID());
- // Check that we're not already marked with a stop reason.
- // Note this thread really shouldn't already be marked as stopped - if we
- // were, that would imply that the kernel signaled us with the thread
- // stopping which we handled and marked as stopped, and that, without an
- // intervening resume, we received another stop. It is more likely that we
- // are missing the marking of a run state somewhere if we find that the
- // thread was marked as stopped.
+ // Check that we're not already marked with a stop reason. Note this thread
+ // really shouldn't already be marked as stopped - if we were, that would
+ // imply that the kernel signaled us with the thread stopping which we
+ // handled and marked as stopped, and that, without an intervening resume,
+ // we received another stop. It is more likely that we are missing the
+ // marking of a run state somewhere if we find that the thread was marked
+ // as stopped.
const StateType thread_state = thread.GetState();
if (!StateIsStoppedState(thread_state, false)) {
// An inferior thread has stopped because of a SIGSTOP we have sent it.
// Generally, these are not important stops and we don't want to report
// them as they are just used to stop other threads when one thread (the
// one with the *real* stop reason) hits a breakpoint (watchpoint,
- // etc...). However, in the case of an asynchronous Interrupt(), this *is*
- // the real stop reason, so we leave the signal intact if this is the
- // thread that was chosen as the triggering thread.
+ // etc...). However, in the case of an asynchronous Interrupt(), this
+ // *is* the real stop reason, so we leave the signal intact if this is
+ // the thread that was chosen as the triggering thread.
if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) {
if (m_pending_notification_tid == thread.GetID())
thread.SetStoppedBySignal(SIGSTOP, &info);
@@ -860,8 +858,8 @@ void NativeProcessLinux::MonitorSignal(const siginfo_t &info,
return;
}
- // Check if debugger should stop at this signal or just ignore it
- // and resume the inferior.
+ // Check if debugger should stop at this signal or just ignore it and resume
+ // the inferior.
if (m_signals_to_ignore.find(signo) != m_signals_to_ignore.end()) {
ResumeThread(thread, thread.GetState(), signo);
return;
@@ -912,9 +910,9 @@ static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,
return true;
}
- // The emulator only fill in the dwarf regsiter numbers (and in some case
- // the generic register numbers). Get the full register info from the
- // register context based on the dwarf register numbers.
+ // The emulator only fill in the dwarf regsiter numbers (and in some case the
+ // generic register numbers). Get the full register info from the register
+ // context based on the dwarf register numbers.
const RegisterInfo *full_reg_info =
emulator_baton->m_reg_context.GetRegisterInfo(
eRegisterKindDWARF, reg_info->kinds[eRegisterKindDWARF]);
@@ -998,8 +996,8 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) {
else
next_flags = ReadFlags(register_context);
} else if (pc_it == baton.m_register_values.end()) {
- // Emulate instruction failed and it haven't changed PC. Advance PC
- // with the size of the current opcode because the emulation of all
+ // Emulate instruction failed and it haven't changed PC. Advance PC with
+ // the size of the current opcode because the emulation of all
// PC modifying instruction should be successful. The failure most
// likely caused by a not supported instruction which don't modify PC.
next_pc = register_context.GetPC() + emulator_ap->GetOpcode().GetByteSize();
@@ -1030,8 +1028,8 @@ NativeProcessLinux::SetupSoftwareSingleStepping(NativeThreadLinux &thread) {
error = SetSoftwareBreakpoint(next_pc, 0);
}
- // If setting the breakpoint fails because next_pc is out of
- // the address space, ignore it and let the debugee segfault.
+ // If setting the breakpoint fails because next_pc is out of the address
+ // space, ignore it and let the debugee segfault.
if (error.GetError() == EIO || error.GetError() == EFAULT) {
return Status();
} else if (error.Fail())
@@ -1162,8 +1160,8 @@ Status NativeProcessLinux::Signal(int signo) {
}
Status NativeProcessLinux::Interrupt() {
- // Pick a running thread (or if none, a not-dead stopped thread) as
- // the chosen thread that will be the stop-reason thread.
+ // Pick a running thread (or if none, a not-dead stopped thread) as the
+ // chosen thread that will be the stop-reason thread.
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
NativeThreadProtocol *running_thread = nullptr;
@@ -1171,15 +1169,15 @@ Status NativeProcessLinux::Interrupt() {
LLDB_LOG(log, "selecting running thread for interrupt target");
for (const auto &thread : m_threads) {
- // If we have a running or stepping thread, we'll call that the
- // target of the interrupt.
+ // If we have a running or stepping thread, we'll call that the target of
+ // the interrupt.
const auto thread_state = thread->GetState();
if (thread_state == eStateRunning || thread_state == eStateStepping) {
running_thread = thread.get();
break;
} else if (!stopped_thread && StateIsStoppedState(thread_state, true)) {
- // Remember the first non-dead stopped thread. We'll use that as a backup
- // if there are no running threads.
+ // Remember the first non-dead stopped thread. We'll use that as a
+ // backup if there are no running threads.
stopped_thread = thread.get();
}
}
@@ -1248,9 +1246,8 @@ ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef &maps_line,
StringExtractor line_extractor(maps_line);
// Format: {address_start_hex}-{address_end_hex} perms offset dev inode
- // pathname
- // perms: rwxp (letter is present if set, '-' if not, final character is
- // p=private, s=shared).
+ // pathname perms: rwxp (letter is present if set, '-' if not, final
+ // character is p=private, s=shared).
// Parse out the starting address
lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0);
@@ -1331,8 +1328,8 @@ Status NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,
// the virtual address space,
// with no perms if it is not mapped.
- // Use an approach that reads memory regions from /proc/{pid}/maps.
- // Assume proc maps entries are in ascending order.
+ // Use an approach that reads memory regions from /proc/{pid}/maps. Assume
+ // proc maps entries are in ascending order.
// FIXME assert if we find differently.
if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
@@ -1383,10 +1380,8 @@ Status NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
// If we made it here, we didn't find an entry that contained the given
- // address. Return the
- // load_addr as start and the amount of bytes betwwen load address and the end
- // of the memory as
- // size.
+ // address. Return the load_addr as start and the amount of bytes betwwen
+ // load address and the end of the memory as size.
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
@@ -1431,8 +1426,8 @@ Status NativeProcessLinux::PopulateMemoryRegionCache() {
if (m_mem_region_cache.empty()) {
// No entries after attempting to read them. This shouldn't happen if
- // /proc/{pid}/maps is supported. Assume we don't support map entries
- // via procfs.
+ // /proc/{pid}/maps is supported. Assume we don't support map entries via
+ // procfs.
m_supports_mem_region = LazyBool::eLazyBoolNo;
LLDB_LOG(log,
"failed to find any procfs maps entries, assuming no support "
@@ -1459,8 +1454,8 @@ void NativeProcessLinux::DoStopIDBumped(uint32_t newBumpId) {
Status NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions,
lldb::addr_t &addr) {
// FIXME implementing this requires the equivalent of
-// InferiorCallPOSIX::InferiorCallMmap, which depends on
-// functional ThreadPlans working with Native*Protocol.
+// InferiorCallPOSIX::InferiorCallMmap, which depends on functional ThreadPlans
+// working with Native*Protocol.
#if 1
return Status("not implemented yet");
#else
@@ -1475,8 +1470,7 @@ Status NativeProcessLinux::AllocateMemory(size_t size, uint32_t permissions,
prot |= eMmapProtExec;
// TODO implement this directly in NativeProcessLinux
- // (and lift to NativeProcessPOSIX if/when that class is
- // refactored out).
+ // (and lift to NativeProcessPOSIX if/when that class is refactored out).
if (InferiorCallMmap(this, addr, 0, size, prot,
eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
m_addr_to_mmap_size[addr] = size;
@@ -1502,10 +1496,9 @@ lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress() {
}
size_t NativeProcessLinux::UpdateThreads() {
- // The NativeProcessLinux monitoring threads are always up to date
- // with respect to thread state and they keep the thread list
- // populated properly. All this method needs to do is return the
- // thread count.
+ // The NativeProcessLinux monitoring threads are always up to date with
+ // respect to thread state and they keep the thread list populated properly.
+ // All this method needs to do is return the thread count.
return m_threads.size();
}
@@ -1515,7 +1508,6 @@ Status NativeProcessLinux::GetSoftwareBreakpointPCOffset(
// set per architecture. Need ARM, MIPS support here.
static const uint8_t g_i386_opcode[] = {0xCC};
static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
- static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
switch (m_arch.GetMachine()) {
case llvm::Triple::x86:
@@ -1527,16 +1519,13 @@ Status NativeProcessLinux::GetSoftwareBreakpointPCOffset(
actual_opcode_size = static_cast<uint32_t>(sizeof(g_s390x_opcode));
return Status();
- case llvm::Triple::ppc64le:
- actual_opcode_size = static_cast<uint32_t>(sizeof(g_ppc64le_opcode));
- return Status();
-
case llvm::Triple::arm:
case llvm::Triple::aarch64:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
+ case llvm::Triple::ppc64le:
// On these architectures the PC don't get updated for breakpoint hits
actual_opcode_size = 0;
return Status();
@@ -1633,161 +1622,11 @@ Status NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(
}
}
-#if 0
-ProcessMessage::CrashReason
-NativeProcessLinux::GetCrashReasonForSIGSEGV(const siginfo_t *info)
-{
- ProcessMessage::CrashReason reason;
- assert(info->si_signo == SIGSEGV);
-
- reason = ProcessMessage::eInvalidCrashReason;
-
- switch (info->si_code)
- {
- default:
- assert(false && "unexpected si_code for SIGSEGV");
- break;
- case SI_KERNEL:
- // Linux will occasionally send spurious SI_KERNEL codes.
- // (this is poorly documented in sigaction)
- // One way to get this is via unaligned SIMD loads.
- reason = ProcessMessage::eInvalidAddress; // for lack of anything better
- break;
- case SEGV_MAPERR:
- reason = ProcessMessage::eInvalidAddress;
- break;
- case SEGV_ACCERR:
- reason = ProcessMessage::ePrivilegedAddress;
- break;
- }
-
- return reason;
-}
-#endif
-
-#if 0
-ProcessMessage::CrashReason
-NativeProcessLinux::GetCrashReasonForSIGILL(const siginfo_t *info)
-{
- ProcessMessage::CrashReason reason;
- assert(info->si_signo == SIGILL);
-
- reason = ProcessMessage::eInvalidCrashReason;
-
- switch (info->si_code)
- {
- default:
- assert(false && "unexpected si_code for SIGILL");
- break;
- case ILL_ILLOPC:
- reason = ProcessMessage::eIllegalOpcode;
- break;
- case ILL_ILLOPN:
- reason = ProcessMessage::eIllegalOperand;
- break;
- case ILL_ILLADR:
- reason = ProcessMessage::eIllegalAddressingMode;
- break;
- case ILL_ILLTRP:
- reason = ProcessMessage::eIllegalTrap;
- break;
- case ILL_PRVOPC:
- reason = ProcessMessage::ePrivilegedOpcode;
- break;
- case ILL_PRVREG:
- reason = ProcessMessage::ePrivilegedRegister;
- break;
- case ILL_COPROC:
- reason = ProcessMessage::eCoprocessorError;
- break;
- case ILL_BADSTK:
- reason = ProcessMessage::eInternalStackError;
- break;
- }
-
- return reason;
-}
-#endif
-
-#if 0
-ProcessMessage::CrashReason
-NativeProcessLinux::GetCrashReasonForSIGFPE(const siginfo_t *info)
-{
- ProcessMessage::CrashReason reason;
- assert(info->si_signo == SIGFPE);
-
- reason = ProcessMessage::eInvalidCrashReason;
-
- switch (info->si_code)
- {
- default:
- assert(false && "unexpected si_code for SIGFPE");
- break;
- case FPE_INTDIV:
- reason = ProcessMessage::eIntegerDivideByZero;
- break;
- case FPE_INTOVF:
- reason = ProcessMessage::eIntegerOverflow;
- break;
- case FPE_FLTDIV:
- reason = ProcessMessage::eFloatDivideByZero;
- break;
- case FPE_FLTOVF:
- reason = ProcessMessage::eFloatOverflow;
- break;
- case FPE_FLTUND:
- reason = ProcessMessage::eFloatUnderflow;
- break;
- case FPE_FLTRES:
- reason = ProcessMessage::eFloatInexactResult;
- break;
- case FPE_FLTINV:
- reason = ProcessMessage::eFloatInvalidOperation;
- break;
- case FPE_FLTSUB:
- reason = ProcessMessage::eFloatSubscriptRange;
- break;
- }
-
- return reason;
-}
-#endif
-
-#if 0
-ProcessMessage::CrashReason
-NativeProcessLinux::GetCrashReasonForSIGBUS(const siginfo_t *info)
-{
- ProcessMessage::CrashReason reason;
- assert(info->si_signo == SIGBUS);
-
- reason = ProcessMessage::eInvalidCrashReason;
-
- switch (info->si_code)
- {
- default:
- assert(false && "unexpected si_code for SIGBUS");
- break;
- case BUS_ADRALN:
- reason = ProcessMessage::eIllegalAlignment;
- break;
- case BUS_ADRERR:
- reason = ProcessMessage::eIllegalAddress;
- break;
- case BUS_OBJERR:
- reason = ProcessMessage::eHardwareError;
- break;
- }
-
- return reason;
-}
-#endif
-
Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
size_t &bytes_read) {
if (ProcessVmReadvSupported()) {
// The process_vm_readv path is about 50 times faster than ptrace api. We
- // want to use
- // this syscall if it is supported.
+ // want to use this syscall if it is supported.
const ::pid_t pid = GetID();
@@ -2094,12 +1933,11 @@ Status NativeProcessLinux::ResumeThread(NativeThreadLinux &thread,
Log *const log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
LLDB_LOG(log, "tid: {0}", thread.GetID());
- // Before we do the resume below, first check if we have a pending
- // stop notification that is currently waiting for
- // all threads to stop. This is potentially a buggy situation since
- // we're ostensibly waiting for threads to stop before we send out the
- // pending notification, and here we are resuming one before we send
- // out the pending stop notification.
+ // Before we do the resume below, first check if we have a pending stop
+ // notification that is currently waiting for all threads to stop. This is
+ // potentially a buggy situation since we're ostensibly waiting for threads
+ // to stop before we send out the pending notification, and here we are
+ // resuming one before we send out the pending stop notification.
if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID) {
LLDB_LOG(log,
"about to resume tid {0} per explicit request but we have a "
@@ -2108,8 +1946,8 @@ Status NativeProcessLinux::ResumeThread(NativeThreadLinux &thread,
thread.GetID(), m_pending_notification_tid);
}
- // Request a resume. We expect this to be synchronous and the system
- // to reflect it is running after this completes.
+ // Request a resume. We expect this to be synchronous and the system to
+ // reflect it is running after this completes.
switch (state) {
case eStateRunning: {
const auto resume_result = thread.Resume(signo);
@@ -2138,8 +1976,8 @@ void NativeProcessLinux::StopRunningThreads(const lldb::tid_t triggering_tid) {
m_pending_notification_tid = triggering_tid;
- // Request a stop for all the thread stops that need to be stopped
- // and are not already known to be stopped.
+ // Request a stop for all the thread stops that need to be stopped and are
+ // not already known to be stopped.
for (const auto &thread : m_threads) {
if (StateIsRunningState(thread->GetState()))
static_cast<NativeThreadLinux *>(thread.get())->RequestStop();
@@ -2185,8 +2023,7 @@ void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) {
if (m_pending_notification_tid != LLDB_INVALID_THREAD_ID &&
StateIsRunningState(thread.GetState())) {
// We will need to wait for this new thread to stop as well before firing
- // the
- // notification.
+ // the notification.
thread.RequestStop();
}
}
@@ -2222,9 +2059,8 @@ void NativeProcessLinux::SigchldHandler() {
}
}
-// Wrapper for ptrace to catch errors and log calls.
-// Note that ptrace sets errno on error because -1 can be a valid result (i.e.
-// for PTRACE_PEEK*)
+// Wrapper for ptrace to catch errors and log calls. Note that ptrace sets
+// errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*)
Status NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
void *data, size_t data_size,
long *result) {
@@ -2422,8 +2258,8 @@ Status NativeProcessLinux::StopTracingForThread(lldb::tid_t thread) {
}
if (iter->second->GetTraceID() == m_pt_proces_trace_id) {
- // traceid maps to the whole process so we have to erase it from the
- // thread group.
+ // traceid maps to the whole process so we have to erase it from the thread
+ // group.
LLDB_LOG(log, "traceid maps to process");
m_pt_traced_thread_group.erase(thread);
}
@@ -2474,8 +2310,8 @@ Status NativeProcessLinux::StopProcessorTracingOnThread(lldb::user_id_t traceid,
if (thread == LLDB_INVALID_THREAD_ID) {
for (auto& iter : m_processor_trace_monitor) {
if (iter.second->GetTraceID() == traceid) {
- // Stopping a trace instance for an individual thread
- // hence there will only be one traceid that can match.
+ // Stopping a trace instance for an individual thread hence there will
+ // only be one traceid that can match.
m_processor_trace_monitor.erase(iter.first);
return error;
}
@@ -2505,8 +2341,8 @@ Status NativeProcessLinux::StopProcessorTracingOnThread(lldb::user_id_t traceid,
LLDB_LOG(log, "UID - {0} , Thread -{1}", traceid, thread);
if (traceid == m_pt_proces_trace_id) {
- // traceid maps to the whole process so we have to erase it from the
- // thread group.
+ // traceid maps to the whole process so we have to erase it from the thread
+ // group.
LLDB_LOG(log, "traceid maps to process");
m_pt_traced_thread_group.erase(thread);
}
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h
index f078c1ac30e2..1c2f786e8d69 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -31,10 +31,10 @@ class Scalar;
namespace process_linux {
/// @class NativeProcessLinux
-/// @brief Manages communication with the inferior (debugee) process.
+/// Manages communication with the inferior (debugee) process.
///
-/// Upon construction, this class prepares and launches an inferior process for
-/// debugging.
+/// Upon construction, this class prepares and launches an inferior process
+/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
class NativeProcessLinux : public NativeProcessProtocol {
@@ -184,20 +184,6 @@ private:
Status SetupSoftwareSingleStepping(NativeThreadLinux &thread);
-#if 0
- static ::ProcessMessage::CrashReason
- GetCrashReasonForSIGSEGV(const siginfo_t *info);
-
- static ::ProcessMessage::CrashReason
- GetCrashReasonForSIGILL(const siginfo_t *info);
-
- static ::ProcessMessage::CrashReason
- GetCrashReasonForSIGFPE(const siginfo_t *info);
-
- static ::ProcessMessage::CrashReason
- GetCrashReasonForSIGBUS(const siginfo_t *info);
-#endif
-
bool HasThreadNoLock(lldb::tid_t thread_id);
bool StopTrackingThread(lldb::tid_t thread_id);
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index cb05416cb6c3..749291684620 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -184,14 +184,14 @@ NativeRegisterContextLinux_arm::ReadRegister(const RegisterInfo *reg_info,
error = ReadRegisterRaw(full_reg, reg_value);
if (error.Success()) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
- // one byte to the right.
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned
+ // value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (reg_value.GetByteSize() > reg_info->byte_size)
reg_value.SetType(reg_info);
}
@@ -558,8 +558,8 @@ uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint(
uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0;
lldb::addr_t real_addr = addr;
- // Check if we are setting watchpoint other than read/write/access
- // Also update watchpoint flag to match Arm write-read bit configuration.
+ // Check if we are setting watchpoint other than read/write/access Also
+ // update watchpoint flag to match Arm write-read bit configuration.
switch (watch_flags) {
case 1:
watch_flags = 2;
@@ -579,9 +579,9 @@ uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint(
if (size == 0 || size > 4)
return LLDB_INVALID_INDEX32;
- // Check 4-byte alignment for hardware watchpoint target address.
- // Below is a hack to recalculate address and size in order to
- // make sure we can watch non 4-byte alligned addresses as well.
+ // Check 4-byte alignment for hardware watchpoint target address. Below is a
+ // hack to recalculate address and size in order to make sure we can watch
+ // non 4-byte alligned addresses as well.
if (addr & 0x03) {
uint8_t watch_mask = (addr & 0x03) + size;
@@ -874,12 +874,10 @@ Status NativeRegisterContextLinux_arm::DoReadRegisterValue(
uint32_t offset, const char *reg_name, uint32_t size,
RegisterValue &value) {
// PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android
- // devices (always return
- // "Bad address"). To avoid using PTRACE_PEEKUSER we read out the full GPR
- // register set instead.
- // This approach is about 4 times slower but the performance overhead is
- // negligible in
- // comparision to processing time in lldb-server.
+ // devices (always return "Bad address"). To avoid using PTRACE_PEEKUSER we
+ // read out the full GPR register set instead. This approach is about 4 times
+ // slower but the performance overhead is negligible in comparision to
+ // processing time in lldb-server.
assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
return Status("Register isn't fit into the size of the GPR area");
@@ -895,13 +893,10 @@ Status NativeRegisterContextLinux_arm::DoReadRegisterValue(
Status NativeRegisterContextLinux_arm::DoWriteRegisterValue(
uint32_t offset, const char *reg_name, const RegisterValue &value) {
// PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android
- // devices (always return
- // "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR
- // register set, modify
- // the requested register and write it back. This approach is about 4 times
- // slower but the
- // performance overhead is negligible in comparision to processing time in
- // lldb-server.
+ // devices (always return "Bad address"). To avoid using PTRACE_POKEUSER we
+ // read out the full GPR register set, modify the requested register and
+ // write it back. This approach is about 4 times slower but the performance
+ // overhead is negligible in comparision to processing time in lldb-server.
assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
return Status("Register isn't fit into the size of the GPR area");
@@ -915,9 +910,8 @@ Status NativeRegisterContextLinux_arm::DoWriteRegisterValue(
// will clear thumb bit of new PC if we are already in thumb mode; that is
// CPSR thumb mode bit is set.
if (offset / sizeof(uint32_t) == gpr_pc_arm) {
- // Check if we are already in thumb mode and
- // thumb bit of current PC is read out to be zero and
- // thumb bit of next PC is read out to be one.
+ // Check if we are already in thumb mode and thumb bit of current PC is
+ // read out to be zero and thumb bit of next PC is read out to be one.
if ((m_gpr_arm[gpr_cpsr_arm] & 0x20) && !(m_gpr_arm[gpr_pc_arm] & 0x01) &&
(value.GetAsUInt32() & 0x01)) {
reg_value &= (~1ull);
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 40e3b80eda74..d0b068550a9e 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -42,7 +42,7 @@ public:
Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
//------------------------------------------------------------------
- // Hardware breakpoints/watchpoint mangement functions
+ // Hardware breakpoints/watchpoint management functions
//------------------------------------------------------------------
uint32_t NumSupportedHardwareBreakpoints() override;
@@ -140,7 +140,7 @@ private:
// occurred.
lldb::addr_t real_addr; // Address value that should cause target to stop.
uint32_t control; // Breakpoint/watchpoint control value.
- uint32_t refcount; // Serves as enable/disable and refernce counter.
+ uint32_t refcount; // Serves as enable/disable and reference counter.
};
struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index c483260a5b2c..41fe446f728c 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -28,8 +28,7 @@
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
// System includes - They have to be included after framework includes because
-// they define some
-// macros which collide with variable names in other modules
+// they define some macros which collide with variable names in other modules
#include <sys/socket.h>
// NT_PRSTATUS and NT_FPREGSET definition
#include <elf.h>
@@ -207,14 +206,14 @@ NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
error = ReadRegisterRaw(full_reg, reg_value);
if (error.Success()) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
- // one byte to the right.
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned
+ // value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (reg_value.GetByteSize() > reg_info->byte_size)
reg_value.SetType(reg_info);
}
@@ -562,8 +561,8 @@ uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint(
uint32_t control_value = 0, wp_index = 0;
lldb::addr_t real_addr = addr;
- // Check if we are setting watchpoint other than read/write/access
- // Also update watchpoint flag to match AArch64 write-read bit configuration.
+ // Check if we are setting watchpoint other than read/write/access Also
+ // update watchpoint flag to match AArch64 write-read bit configuration.
switch (watch_flags) {
case 1:
watch_flags = 2;
@@ -581,9 +580,9 @@ uint32_t NativeRegisterContextLinux_arm64::SetHardwareWatchpoint(
if (size != 1 && size != 2 && size != 4 && size != 8)
return LLDB_INVALID_INDEX32;
- // Check 8-byte alignment for hardware watchpoint target address.
- // Below is a hack to recalculate address and size in order to
- // make sure we can watch non 8-byte alligned addresses as well.
+ // Check 8-byte alignment for hardware watchpoint target address. Below is a
+ // hack to recalculate address and size in order to make sure we can watch
+ // non 8-byte alligned addresses as well.
if (addr & 0x07) {
uint8_t watch_mask = (addr & 0x07) + size;
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
index ab3c881ead59..c859d4249d05 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h
@@ -42,7 +42,7 @@ public:
Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
//------------------------------------------------------------------
- // Hardware breakpoints/watchpoint mangement functions
+ // Hardware breakpoints/watchpoint management functions
//------------------------------------------------------------------
uint32_t NumSupportedHardwareBreakpoints() override;
@@ -140,7 +140,7 @@ private:
// occurred.
lldb::addr_t real_addr; // Address value that should cause target to stop.
uint32_t control; // Breakpoint/watchpoint control value.
- uint32_t refcount; // Serves as enable/disable and refernce counter.
+ uint32_t refcount; // Serves as enable/disable and reference counter.
};
struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
index 32c04a4374e6..69194b3c0663 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
@@ -140,9 +140,9 @@ NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64(
break;
}
- // Initialize m_iovec to point to the buffer and buffer size
- // using the conventions of Berkeley style UIO structures, as required
- // by PTRACE extensions.
+ // Initialize m_iovec to point to the buffer and buffer size using the
+ // conventions of Berkeley style UIO structures, as required by PTRACE
+ // extensions.
m_iovec.iov_base = &m_msa;
m_iovec.iov_len = sizeof(MSA_linux_mips);
@@ -337,7 +337,8 @@ lldb_private::Status NativeRegisterContextLinux_mips64::WriteRegister(
uint8_t byte_size = reg_info->byte_size;
lldbassert(reg_info->byte_offset < sizeof(UserArea));
- // Initialise the FP and MSA buffers by reading all co-processor 1 registers
+ // Initialise the FP and MSA buffers by reading all co-processor 1
+ // registers
ReadCP1();
if (IsFPR(reg_index)) {
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
index ea854dfa1dc6..6aa4af64ab51 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
@@ -26,8 +26,7 @@
#include "Plugins/Process/Utility/RegisterInfoPOSIX_ppc64le.h"
// System includes - They have to be included after framework includes because
-// they define some
-// macros which collide with variable names in other modules
+// they define some macros which collide with variable names in other modules
#include <sys/socket.h>
#include <elf.h>
#include <asm/ptrace.h>
@@ -50,6 +49,7 @@ static const uint32_t g_gpr_regnums_ppc64le[] = {
gpr_pc_ppc64le, gpr_msr_ppc64le, gpr_origr3_ppc64le, gpr_ctr_ppc64le,
gpr_lr_ppc64le, gpr_xer_ppc64le, gpr_cr_ppc64le, gpr_softe_ppc64le,
gpr_trap_ppc64le,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
};
static const uint32_t g_fpr_regnums_ppc64le[] = {
@@ -62,6 +62,7 @@ static const uint32_t g_fpr_regnums_ppc64le[] = {
fpr_f24_ppc64le, fpr_f25_ppc64le, fpr_f26_ppc64le, fpr_f27_ppc64le,
fpr_f28_ppc64le, fpr_f29_ppc64le, fpr_f30_ppc64le, fpr_f31_ppc64le,
fpr_fpscr_ppc64le,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
};
static const uint32_t g_vmx_regnums_ppc64le[] = {
@@ -74,6 +75,7 @@ static const uint32_t g_vmx_regnums_ppc64le[] = {
vmx_vr24_ppc64le, vmx_vr25_ppc64le, vmx_vr26_ppc64le, vmx_vr27_ppc64le,
vmx_vr28_ppc64le, vmx_vr29_ppc64le, vmx_vr30_ppc64le, vmx_vr31_ppc64le,
vmx_vscr_ppc64le, vmx_vrsave_ppc64le,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
};
static const uint32_t g_vsx_regnums_ppc64le[] = {
@@ -93,6 +95,7 @@ static const uint32_t g_vsx_regnums_ppc64le[] = {
vsx_vs52_ppc64le, vsx_vs53_ppc64le, vsx_vs54_ppc64le, vsx_vs55_ppc64le,
vsx_vs56_ppc64le, vsx_vs57_ppc64le, vsx_vs58_ppc64le, vsx_vs59_ppc64le,
vsx_vs60_ppc64le, vsx_vs61_ppc64le, vsx_vs62_ppc64le, vsx_vs63_ppc64le,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
};
namespace {
@@ -565,8 +568,8 @@ uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint(
lldb::addr_t real_addr = addr;
uint32_t rw_mode = 0;
- // Check if we are setting watchpoint other than read/write/access
- // Update watchpoint flag to match ppc64le write-read bit configuration.
+ // Check if we are setting watchpoint other than read/write/access Update
+ // watchpoint flag to match ppc64le write-read bit configuration.
switch (watch_flags) {
case eWatchpointKindWrite:
rw_mode = PPC_BREAKPOINT_TRIGGER_WRITE;
@@ -587,9 +590,9 @@ uint32_t NativeRegisterContextLinux_ppc64le::SetHardwareWatchpoint(
if (size != 1 && size != 2 && size != 4 && size != 8)
return LLDB_INVALID_INDEX32;
- // Check 8-byte alignment for hardware watchpoint target address.
- // Below is a hack to recalculate address and size in order to
- // make sure we can watch non 8-byte alligned addresses as well.
+ // Check 8-byte alignment for hardware watchpoint target address. Below is a
+ // hack to recalculate address and size in order to make sure we can watch
+ // non 8-byte alligned addresses as well.
if (addr & 0x07) {
addr_t begin = llvm::alignDown(addr, 8);
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h
index bb25af80d02c..2c4471962ad0 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.h
@@ -19,7 +19,7 @@
#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
-#include "RegisterInfos_ppc64le.h"
+#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
#undef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
namespace lldb_private {
@@ -49,7 +49,7 @@ public:
Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
//------------------------------------------------------------------
- // Hardware watchpoint mangement functions
+ // Hardware watchpoint management functions
//------------------------------------------------------------------
uint32_t NumSupportedHardwareWatchpoints() override;
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
index 021394ab154b..36da2b001054 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
@@ -10,7 +10,7 @@
#if defined(__s390x__) && defined(__linux__)
#include "NativeRegisterContextLinux_s390x.h"
-
+#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -372,10 +372,10 @@ Status NativeRegisterContextLinux_s390x::ReadAllRegisterValues(
DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4);
dst += 4;
- // To enable inferior function calls while the process is stopped in
- // an interrupted system call, we need to clear the system call flag.
- // It will be restored to its original value by WriteAllRegisterValues.
- // Again we ignore error if the regset is unsupported.
+ // To enable inferior function calls while the process is stopped in an
+ // interrupted system call, we need to clear the system call flag. It will be
+ // restored to its original value by WriteAllRegisterValues. Again we ignore
+ // error if the regset is unsupported.
uint32_t system_call = 0;
DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index 84ffe9b6e420..87f4b8da053e 100755
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -329,9 +329,9 @@ NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
break;
}
- // Initialize m_iovec to point to the buffer and buffer size
- // using the conventions of Berkeley style UIO structures, as required
- // by PTRACE extensions.
+ // Initialize m_iovec to point to the buffer and buffer size using the
+ // conventions of Berkeley style UIO structures, as required by PTRACE
+ // extensions.
m_iovec.iov_base = &m_fpr;
m_iovec.iov_len = sizeof(m_fpr);
@@ -420,14 +420,14 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
error = ReadRegisterRaw(full_reg, reg_value);
if (error.Success()) {
- // If our read was not aligned (for ah,bh,ch,dh), shift our returned value
- // one byte to the right.
+ // If our read was not aligned (for ah,bh,ch,dh), shift our returned
+ // value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
reg_value.SetUInt64(reg_value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
- // then
- // use the type specified by reg_info rather than the uint64_t default
+ // then use the type specified by reg_info rather than the uint64_t
+ // default
if (reg_value.GetByteSize() > reg_info->byte_size)
reg_value.SetType(reg_info);
}
@@ -448,7 +448,8 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
reg_value.SetBytes(m_fpr.fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
reg_info->byte_size, byte_order);
if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
- // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+ // Concatenate ymm using the register halves in xmm.bytes and
+ // ymmh.bytes
if (CopyXSTATEtoYMM(reg, byte_order))
reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
reg_info->byte_size, byte_order);
@@ -492,8 +493,7 @@ NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
// Byte offsets of all registers are calculated wrt 'UserArea' structure.
// However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
// and stores them in 'm_fpr' (of type FPR structure). To extract values of
- // fpu
- // registers, m_fpr should be read at byte offsets calculated wrt to FPR
+ // fpu registers, m_fpr should be read at byte offsets calculated wrt to FPR
// structure.
// Since, FPR structure is also one of the member of UserArea structure.
@@ -599,11 +599,10 @@ Status NativeRegisterContextLinux_x86_64::WriteRegister(
// Get pointer to m_fpr.fxsave variable and set the data to it.
// Byte offsets of all registers are calculated wrt 'UserArea' structure.
- // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only
- // fpu
- // registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu registers
- // should
- // be written in m_fpr at byte offsets calculated wrt FPR structure.
+ // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
+ // only fpu registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu
+ // registers should be written in m_fpr at byte offsets calculated wrt
+ // FPR structure.
// Since, FPR structure is also one of the member of UserArea structure.
// byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
@@ -1093,8 +1092,7 @@ Status NativeRegisterContextLinux_x86_64::SetHardwareWatchpointWithIndex(
if (error.Fail())
return error;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // set bits 1, 3, 5, or 7
+ // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7
uint64_t enable_bit = 1 << (2 * wp_index);
// set bits 16-17, 20-21, 24-25, or 28-29
@@ -1132,8 +1130,8 @@ bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(
RegisterValue reg_value;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
+ // the debug status register (DR6)
Status error = ReadRegisterRaw(m_reg_info.first_dr + 6, reg_value);
if (error.Fail())
return false;
@@ -1143,9 +1141,9 @@ bool NativeRegisterContextLinux_x86_64::ClearHardwareWatchpoint(
if (error.Fail())
return false;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
- // of the debug control register (DR7)
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
+ // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
+ // (DR7)
error = ReadRegisterRaw(m_reg_info.first_dr + 7, reg_value);
if (error.Fail())
return false;
diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index 0db3bd56b8e4..4ab2a9ae6245 100644
--- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -211,8 +211,8 @@ Status NativeThreadLinux::Resume(uint32_t signo) {
m_stop_info.reason = StopReason::eStopReasonNone;
m_stop_description.clear();
- // If watchpoints have been set, but none on this thread,
- // then this is a new thread. So set all existing watchpoints.
+ // If watchpoints have been set, but none on this thread, then this is a new
+ // thread. So set all existing watchpoints.
if (m_watchpoint_index_map.empty()) {
NativeProcessLinux &process = GetProcess();
@@ -263,8 +263,8 @@ Status NativeThreadLinux::SingleStep(uint32_t signo) {
data = signo;
// If hardware single-stepping is not supported, we just do a continue. The
- // breakpoint on the
- // next instruction has been setup in NativeProcessLinux::Resume.
+ // breakpoint on the next instruction has been setup in
+ // NativeProcessLinux::Resume.
return NativeProcessLinux::PtraceWrapper(
GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP
: PTRACE_CONT,
diff --git a/source/Plugins/Process/Linux/ProcessorTrace.h b/source/Plugins/Process/Linux/ProcessorTrace.h
index 6603c7d60478..6fd918c2bb58 100644
--- a/source/Plugins/Process/Linux/ProcessorTrace.h
+++ b/source/Plugins/Process/Linux/ProcessorTrace.h
@@ -34,7 +34,7 @@ namespace process_linux {
// a key to the tracing instance and trace manipulations could be
// performed using the trace id.
//
-// The traace id could map to trace instances for a group of threads
+// The trace id could map to trace instances for a group of threads
// (spanning to all the threads in the process) or a single thread.
// The kernel interface for us is the perf_event_open.
// ---------------------------------------------------------------------
diff --git a/source/Plugins/Process/Linux/SingleStepCheck.cpp b/source/Plugins/Process/Linux/SingleStepCheck.cpp
index 251cb4b2f10a..c57a2daf2275 100644
--- a/source/Plugins/Process/Linux/SingleStepCheck.cpp
+++ b/source/Plugins/Process/Linux/SingleStepCheck.cpp
@@ -59,9 +59,9 @@ struct ChildDeleter {
bool WorkaroundNeeded() {
// We shall spawn a child, and use it to verify the debug capabilities of the
- // cpu. We shall iterate through the cpus, bind the child to each one in turn,
- // and verify that single-stepping works on that cpu. A workaround is needed
- // if we find at least one broken cpu.
+ // cpu. We shall iterate through the cpus, bind the child to each one in
+ // turn, and verify that single-stepping works on that cpu. A workaround is
+ // needed if we find at least one broken cpu.
Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD);
::pid_t child_pid = fork();
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
index 3d9f498b1e9a..116155d9a232 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
@@ -59,15 +59,6 @@ bool CommunicationKDP::SendRequestPacket(
return SendRequestPacketNoLock(request_packet);
}
-#if 0
-typedef struct {
- uint8_t request; // Either: CommandType | ePacketTypeRequest, or CommandType | ePacketTypeReply
- uint8_t sequence;
- uint16_t length; // Length of entire packet including this header
- uint32_t key; // Session key
-} kdp_hdr_t;
-#endif
-
void CommunicationKDP::MakeRequestPacketHeader(CommandType request_type,
PacketStreamType &request_packet,
uint16_t request_length) {
@@ -127,16 +118,14 @@ bool CommunicationKDP::SendRequestAndGetReply(
}
} else if (reply_sequence_id > request_sequence_id) {
// Sequence ID was greater than the sequence ID of the packet we
- // sent, something
- // is really wrong...
+ // sent, something is really wrong...
reply_packet.Clear();
return false;
} else {
- // The reply sequence ID was less than our current packet's sequence
- // ID
- // so we should keep trying to get a response because this was a
- // response
- // for a previous packet that we must have retried.
+ // The reply sequence ID was less than our current packet's
+ // sequence ID so we should keep trying to get a response because
+ // this was a response for a previous packet that we must have
+ // retried.
}
} else {
// Break and retry sending the packet as we didn't get a response due
@@ -186,7 +175,7 @@ bool CommunicationKDP::GetSequenceMutex(
bool CommunicationKDP::WaitForNotRunningPrivate(
const std::chrono::microseconds &timeout) {
- return m_is_running.WaitForValueEqualTo(false, timeout, NULL);
+ return m_is_running.WaitForValueEqualTo(false, timeout);
}
size_t
@@ -324,9 +313,9 @@ bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len,
offset = 2;
const uint16_t length = packet.GetU16(&offset);
if (length <= bytes_available) {
- // We have an entire packet ready, we need to copy the data
- // bytes into a buffer that will be owned by the packet and
- // erase the bytes from our communcation buffer "m_bytes"
+ // We have an entire packet ready, we need to copy the data bytes into
+ // a buffer that will be owned by the packet and erase the bytes from
+ // our communcation buffer "m_bytes"
packet.SetData(DataBufferSP(new DataBufferHeap(&m_bytes[0], length)));
m_bytes.erase(0, length);
@@ -341,8 +330,8 @@ bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len,
} break;
default:
- // Unrecognized reply command byte, erase this byte and try to get back on
- // track
+ // Unrecognized reply command byte, erase this byte and try to get back
+ // on track
if (log)
log->Printf("CommunicationKDP::%s: tossing junk byte: 0x%2.2x",
__FUNCTION__, (uint8_t)m_bytes[0]);
@@ -436,34 +425,6 @@ bool CommunicationKDP::SendRequestVersion() {
return false;
}
-#if 0 // Disable KDP_IMAGEPATH for now, it seems to hang the KDP connection...
-const char *
-CommunicationKDP::GetImagePath ()
-{
- if (m_image_path.empty())
- SendRequestImagePath();
- return m_image_path.c_str();
-}
-
-bool
-CommunicationKDP::SendRequestImagePath ()
-{
- PacketStreamType request_packet (Stream::eBinary, m_addr_byte_size, m_byte_order);
- const CommandType command = KDP_IMAGEPATH;
- const uint32_t command_length = 8;
- MakeRequestPacketHeader (command, request_packet, command_length);
- DataExtractor reply_packet;
- if (SendRequestAndGetReply (command, request_packet, reply_packet))
- {
- const char *path = reply_packet.PeekCStr(8);
- if (path && path[0])
- m_kernel_version.assign (path);
- return true;
- }
- return false;
-}
-#endif
-
uint32_t CommunicationKDP::GetCPUMask() {
if (!HostInfoIsValid())
SendRequestHostInfo();
@@ -495,7 +456,7 @@ lldb_private::UUID CommunicationKDP::GetUUID() {
if (uuid_str.size() < 32)
return uuid;
- if (uuid.SetFromCString(uuid_str.c_str()) == 0) {
+ if (uuid.SetFromStringRef(uuid_str) == 0) {
UUID invalid_uuid;
return invalid_uuid;
}
@@ -1245,8 +1206,8 @@ uint32_t CommunicationKDP::SendRequestReadRegisters(uint32_t cpu,
if (src) {
::memcpy(dst, src, bytes_to_copy);
error.Clear();
- // Return the number of bytes we could have returned regardless if
- // we copied them or not, just so we know when things don't match up
+ // Return the number of bytes we could have returned regardless if we
+ // copied them or not, just so we know when things don't match up
return src_len;
}
}
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index f01f1ace583c..2e707ab2e363 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -172,10 +172,10 @@ ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp)
//----------------------------------------------------------------------
ProcessKDP::~ProcessKDP() {
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
}
@@ -226,9 +226,9 @@ bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) {
Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) {
Status error;
- // Don't let any JIT happen when doing KDP as we can't allocate
- // memory and we don't want to be mucking with threads that might
- // already be handling exceptions
+ // Don't let any JIT happen when doing KDP as we can't allocate memory and we
+ // don't want to be mucking with threads that might already be handling
+ // exceptions
SetCanJIT(false);
if (remote_url.empty()) {
@@ -282,16 +282,15 @@ Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) {
if (m_comm.RemoteIsEFI()) {
// Select an invalid plugin name for the dynamic loader so one
- // doesn't get used
- // since EFI does its own manual loading via python scripting
+ // doesn't get used since EFI does its own manual loading via
+ // python scripting
static ConstString g_none_dynamic_loader("none");
m_dyld_plugin_name = g_none_dynamic_loader;
if (kernel_uuid.IsValid()) {
- // If EFI passed in a UUID= try to lookup UUID
- // The slide will not be provided. But the UUID
- // lookup will be used to launch EFI debug scripts
- // from the dSYM, that can load all of the symbols.
+ // If EFI passed in a UUID= try to lookup UUID The slide will not
+ // be provided. But the UUID lookup will be used to launch EFI
+ // debug scripts from the dSYM, that can load all of the symbols.
ModuleSpec module_spec;
module_spec.GetUUID() = kernel_uuid;
module_spec.GetArchitecture() = target.GetArchitecture();
@@ -386,7 +385,7 @@ ProcessKDP::DoAttachToProcessWithID(lldb::pid_t attach_pid,
const ProcessAttachInfo &attach_info) {
Status error;
error.SetErrorString(
- "attach to process by ID is not suppported in kdp remote debugging");
+ "attach to process by ID is not supported in kdp remote debugging");
return error;
}
@@ -395,7 +394,7 @@ ProcessKDP::DoAttachToProcessWithName(const char *process_name,
const ProcessAttachInfo &attach_info) {
Status error;
error.SetErrorString(
- "attach to process by name is not suppported in kdp remote debugging");
+ "attach to process by name is not supported in kdp remote debugging");
return error;
}
@@ -443,8 +442,8 @@ Status ProcessKDP::DoResume() {
StateAsCString(thread_resume_state));
switch (thread_resume_state) {
case eStateSuspended:
- // Nothing to do here when a thread will stay suspended
- // we just leave the CPU mask bit set to zero for the thread
+ // Nothing to do here when a thread will stay suspended we just leave the
+ // CPU mask bit set to zero for the thread
if (log)
log->Printf("ProcessKDP::DoResume() = suspended???");
break;
@@ -535,8 +534,8 @@ bool ProcessKDP::UpdateThreadList(ThreadList &old_thread_list,
}
void ProcessKDP::RefreshStateAfterStop() {
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
m_thread_list.RefreshStateAfterStop();
}
@@ -545,9 +544,9 @@ Status ProcessKDP::DoHalt(bool &caused_stop) {
if (m_comm.IsRunning()) {
if (m_destroy_in_process) {
- // If we are attemping to destroy, we need to not return an error to
- // Halt or DoDestroy won't get called.
- // We are also currently running, so send a process stopped event
+ // If we are attempting to destroy, we need to not return an error to Halt
+ // or DoDestroy won't get called. We are also currently running, so send
+ // a process stopped event
SetPrivateState(eStateStopped);
} else {
error.SetErrorString("KDP cannot interrupt a running kernel");
@@ -563,8 +562,8 @@ Status ProcessKDP::DoDetach(bool keep_stopped) {
log->Printf("ProcessKDP::DoDetach(keep_stopped = %i)", keep_stopped);
if (m_comm.IsRunning()) {
- // We are running and we can't interrupt a running kernel, so we need
- // to just close the connection to the kernel and hope for the best
+ // We are running and we can't interrupt a running kernel, so we need to
+ // just close the connection to the kernel and hope for the best
} else {
// If we are going to keep the target stopped, then don't send the
// disconnect message.
@@ -647,14 +646,14 @@ size_t ProcessKDP::DoWriteMemory(addr_t addr, const void *buf, size_t size,
lldb::addr_t ProcessKDP::DoAllocateMemory(size_t size, uint32_t permissions,
Status &error) {
error.SetErrorString(
- "memory allocation not suppported in kdp remote debugging");
+ "memory allocation not supported in kdp remote debugging");
return LLDB_INVALID_ADDRESS;
}
Status ProcessKDP::DoDeallocateMemory(lldb::addr_t addr) {
Status error;
error.SetErrorString(
- "memory deallocation not suppported in kdp remote debugging");
+ "memory deallocation not supported in kdp remote debugging");
return error;
}
@@ -701,14 +700,14 @@ Status ProcessKDP::DisableBreakpointSite(BreakpointSite *bp_site) {
Status ProcessKDP::EnableWatchpoint(Watchpoint *wp, bool notify) {
Status error;
error.SetErrorString(
- "watchpoints are not suppported in kdp remote debugging");
+ "watchpoints are not supported in kdp remote debugging");
return error;
}
Status ProcessKDP::DisableWatchpoint(Watchpoint *wp, bool notify) {
Status error;
error.SetErrorString(
- "watchpoints are not suppported in kdp remote debugging");
+ "watchpoints are not supported in kdp remote debugging");
return error;
}
@@ -717,7 +716,7 @@ void ProcessKDP::Clear() { m_thread_list.Clear(); }
Status ProcessKDP::DoSignal(int signo) {
Status error;
error.SetErrorString(
- "sending signals is not suppported in kdp remote debugging");
+ "sending signals is not supported in kdp remote debugging");
return error;
}
diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
index 1902cc492ff4..7fca0fc24fdb 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
@@ -52,11 +52,11 @@ ThreadKDP::~ThreadKDP() {
const char *ThreadKDP::GetName() {
if (m_thread_name.empty())
- return NULL;
+ return nullptr;
return m_thread_name.c_str();
}
-const char *ThreadKDP::GetQueueName() { return NULL; }
+const char *ThreadKDP::GetQueueName() { return nullptr; }
void ThreadKDP::RefreshStateAfterStop() {
// Invalidate all registers in our register context. We don't set "force" to
@@ -65,8 +65,8 @@ void ThreadKDP::RefreshStateAfterStop() {
// context by the time this function gets called. The KDPRegisterContext
// class has been made smart enough to detect when it needs to invalidate
// which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
+ // register supply functions where they check the process stop ID and do the
+ // right thing.
const bool force = false;
lldb::RegisterContextSP reg_ctx_sp(GetRegisterContext());
if (reg_ctx_sp)
@@ -79,8 +79,8 @@ void ThreadKDP::Dump(Log *log, uint32_t index) {}
bool ThreadKDP::ShouldStop(bool &step_more) { return true; }
lldb::RegisterContextSP ThreadKDP::GetRegisterContext() {
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
return m_reg_context_sp;
}
@@ -119,7 +119,7 @@ ThreadKDP::CreateRegisterContextForFrame(StackFrame *frame) {
}
} else {
Unwind *unwinder = GetUnwinder();
- if (unwinder)
+ if (unwinder != nullptr)
reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
@@ -151,8 +151,8 @@ void ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION(
const uint32_t exc_type = exc_reply_packet.GetU32(&offset);
const uint32_t exc_code = exc_reply_packet.GetU32(&offset);
const uint32_t exc_subcode = exc_reply_packet.GetU32(&offset);
- // We have to make a copy of the stop info because the thread list
- // will iterate through the threads and clear all stop infos..
+ // We have to make a copy of the stop info because the thread list will
+ // iterate through the threads and clear all stop infos..
// Let the StopInfoMachException::CreateStopReasonWithMachException()
// function update the PC if needed as we might hit a software breakpoint
diff --git a/source/Plugins/Process/NetBSD/CMakeLists.txt b/source/Plugins/Process/NetBSD/CMakeLists.txt
index 5b2cef8b847b..92a6014ced07 100644
--- a/source/Plugins/Process/NetBSD/CMakeLists.txt
+++ b/source/Plugins/Process/NetBSD/CMakeLists.txt
@@ -1,7 +1,3 @@
-include_directories(.)
-include_directories(../POSIX)
-include_directories(../Utility)
-
add_lldb_library(lldbPluginProcessNetBSD PLUGIN
NativeProcessNetBSD.cpp
NativeRegisterContextNetBSD.cpp
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 387f04afa5b4..1a4cb21d000e 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -24,8 +24,7 @@
#include "llvm/Support/Errno.h"
// System includes - They have to be included after framework includes because
-// they define some
-// macros which collide with variable names in other modules
+// they define some macros which collide with variable names in other modules
// clang-format off
#include <sys/types.h>
#include <sys/ptrace.h>
@@ -93,17 +92,19 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
}
LLDB_LOG(log, "inferior started, now in stopped state");
- ArchSpec arch;
- if ((status = ResolveProcessArchitecture(pid, arch)).Fail())
- return status.ToError();
+ ProcessInstanceInfo Info;
+ if (!Host::GetProcessInfo(pid, Info)) {
+ return llvm::make_error<StringError>("Cannot get process architecture",
+ llvm::inconvertibleErrorCode());
+ }
// Set the architecture to the exe architecture.
LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
- arch.GetArchitectureName());
+ Info.GetArchitecture().GetArchitectureName());
std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
- arch, mainloop));
+ Info.GetArchitecture(), mainloop));
status = process_up->ReinitializeThreads();
if (status.Fail())
@@ -111,7 +112,7 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
for (const auto &thread : process_up->m_threads)
static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
- process_up->SetState(StateType::eStateStopped);
+ process_up->SetState(StateType::eStateStopped, false);
return std::move(process_up);
}
@@ -124,15 +125,16 @@ NativeProcessNetBSD::Factory::Attach(
LLDB_LOG(log, "pid = {0:x}", pid);
// Retrieve the architecture for the running process.
- ArchSpec arch;
- Status status = ResolveProcessArchitecture(pid, arch);
- if (!status.Success())
- return status.ToError();
+ ProcessInstanceInfo Info;
+ if (!Host::GetProcessInfo(pid, Info)) {
+ return llvm::make_error<StringError>("Cannot get process architecture",
+ llvm::inconvertibleErrorCode());
+ }
- std::unique_ptr<NativeProcessNetBSD> process_up(
- new NativeProcessNetBSD(pid, -1, native_delegate, arch, mainloop));
+ std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
+ pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
- status = process_up->Attach();
+ Status status = process_up->Attach();
if (!status.Success())
return status.ToError();
@@ -349,8 +351,8 @@ NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) {
return error;
} else
LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
- // First try probing for a breakpoint at a software breakpoint location: PC
- // - breakpoint size.
+ // First try probing for a breakpoint at a software breakpoint location: PC -
+ // breakpoint size.
const lldb::addr_t initial_pc_addr =
context.GetPCfromBreakpointLocation();
lldb::addr_t breakpoint_addr = initial_pc_addr;
@@ -559,8 +561,8 @@ Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
"descending memory map entries detected, unexpected");
prev_base_address = proc_entry_info.GetRange().GetRangeBase();
UNUSED_IF_ASSERT_DISABLED(prev_base_address);
- // If the target address comes before this entry, indicate distance to
- // next region.
+ // If the target address comes before this entry, indicate distance to next
+ // region.
if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetByteSize(
@@ -579,9 +581,8 @@ Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
// parsed.
}
// If we made it here, we didn't find an entry that contained the given
- // address. Return the
- // load_addr as start and the amount of bytes betwwen load address and the
- // end of the memory as size.
+ // address. Return the load_addr as start and the amount of bytes betwwen
+ // load address and the end of the memory as size.
range_info.GetRange().SetRangeBase(load_addr);
range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
@@ -641,8 +642,8 @@ Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
free(vm);
if (m_mem_region_cache.empty()) {
- // No entries after attempting to read them. This shouldn't happen.
- // Assume we don't support map entries.
+ // No entries after attempting to read them. This shouldn't happen. Assume
+ // we don't support map entries.
LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
"for memory region metadata retrieval");
m_supports_mem_region = LazyBool::eLazyBoolNo;
@@ -778,8 +779,8 @@ Status NativeProcessNetBSD::Attach() {
return status;
int wstatus;
- // Need to use WALLSIG otherwise we receive an error with errno=ECHLD
- // At this point we should have a thread stopped if waitpid succeeds.
+ // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
+ // point we should have a thread stopped if waitpid succeeds.
if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0)
return Status(errno, eErrorTypePOSIX);
@@ -871,13 +872,13 @@ NativeProcessNetBSD::GetAuxvData() const {
*/
size_t auxv_size = 100 * sizeof(AuxInfo);
- ErrorOr<std::unique_ptr<MemoryBuffer>> buf =
- llvm::MemoryBuffer::getNewMemBuffer(auxv_size);
+ ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
+ llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
struct ptrace_io_desc io;
io.piod_op = PIOD_READ_AUXV;
io.piod_offs = 0;
- io.piod_addr = const_cast<void *>(static_cast<const void *>(buf.get()->getBufferStart()));
+ io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
io.piod_len = auxv_size;
Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
@@ -888,7 +889,7 @@ NativeProcessNetBSD::GetAuxvData() const {
if (io.piod_len < 1)
return std::error_code(ECANCELED, std::generic_category());
- return buf;
+ return std::move(buf);
}
Status NativeProcessNetBSD::ReinitializeThreads() {
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 7090fce34fc9..142f74ecf194 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -20,10 +20,10 @@
namespace lldb_private {
namespace process_netbsd {
/// @class NativeProcessNetBSD
-/// @brief Manages communication with the inferior (debugee) process.
+/// Manages communication with the inferior (debugee) process.
///
-/// Upon construction, this class prepares and launches an inferior process for
-/// debugging.
+/// Upon construction, this class prepares and launches an inferior process
+/// for debugging.
///
/// Changes in the inferior process state are broadcasted.
class NativeProcessNetBSD : public NativeProcessProtocol {
diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 347c15ae5b23..16b6f2c52dd5 100644
--- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -161,8 +161,8 @@ static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec &target_arch) {
assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
"Register setting path assumes this is a 64-bit host");
- // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
- // x86_64 register context.
+ // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64
+ // register context.
return new RegisterContextNetBSD_x86_64(target_arch);
}
@@ -805,8 +805,7 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
if (error.Fail())
return error;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // set bits 1, 3, 5, or 7
+ // for watchpoints 0, 1, 2, or 3, respectively, set bits 1, 3, 5, or 7
uint64_t enable_bit = 1 << (2 * wp_index);
// set bits 16-17, 20-21, 24-25, or 28-29
@@ -845,8 +844,8 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
RegisterValue reg_value;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits 0, 1, 2, or 3 of the debug status register (DR6)
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
+ // the debug status register (DR6)
const RegisterInfo *const reg_info_dr6 =
GetRegisterInfoAtIndex(lldb_dr6_x86_64);
Status error = ReadRegister(reg_info_dr6, reg_value);
@@ -858,9 +857,9 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
if (error.Fail())
return false;
- // for watchpoints 0, 1, 2, or 3, respectively,
- // clear bits {0-1,16-19}, {2-3,20-23}, {4-5,24-27}, or {6-7,28-31}
- // of the debug control register (DR7)
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
+ // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
+ // (DR7)
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
error = ReadRegister(reg_info_dr7, reg_value);
diff --git a/source/Plugins/Process/POSIX/CMakeLists.txt b/source/Plugins/Process/POSIX/CMakeLists.txt
index d9a4508df0a3..f058e01c7439 100644
--- a/source/Plugins/Process/POSIX/CMakeLists.txt
+++ b/source/Plugins/Process/POSIX/CMakeLists.txt
@@ -1,6 +1,3 @@
-include_directories(.)
-include_directories(../Utility)
-
add_lldb_library(lldbPluginProcessPOSIX PLUGIN
CrashReason.cpp
ProcessMessage.cpp
diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp
index 864418c90031..4b24d31226a9 100644
--- a/source/Plugins/Process/POSIX/CrashReason.cpp
+++ b/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -47,8 +47,7 @@ CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) {
#ifdef SI_KERNEL
case SI_KERNEL:
// Some platforms will occasionally send nonstandard spurious SI_KERNEL
- // codes.
- // One way to get this is via unaligned SIMD loads.
+ // codes. One way to get this is via unaligned SIMD loads.
return CrashReason::eInvalidAddress; // for lack of anything better
#endif
case SEGV_MAPERR:
diff --git a/source/Plugins/Process/Utility/CMakeLists.txt b/source/Plugins/Process/Utility/CMakeLists.txt
index 3780fb5e4c18..b43756acea63 100644
--- a/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/source/Plugins/Process/Utility/CMakeLists.txt
@@ -1,5 +1,3 @@
-include_directories(../../../Utility/)
-
add_lldb_library(lldbPluginProcessUtility PLUGIN
DynamicRegisterInfo.cpp
FreeBSDSignals.cpp
@@ -60,7 +58,6 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN
lldbSymbol
lldbTarget
lldbUtility
- lldbPluginProcessElfCore
LINK_COMPONENTS
Support
)
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 61e5bf4481d6..5f34e9915ede 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/StringConvert.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StringExtractor.h"
@@ -20,21 +21,42 @@
using namespace lldb;
using namespace lldb_private;
-DynamicRegisterInfo::DynamicRegisterInfo()
- : m_regs(), m_sets(), m_set_reg_nums(), m_set_names(), m_value_regs_map(),
- m_invalidate_regs_map(), m_dynamic_reg_size_map(),
- m_reg_data_byte_size(0), m_finalized(false) {}
-
DynamicRegisterInfo::DynamicRegisterInfo(
const lldb_private::StructuredData::Dictionary &dict,
- const lldb_private::ArchSpec &arch)
- : m_regs(), m_sets(), m_set_reg_nums(), m_set_names(), m_value_regs_map(),
- m_invalidate_regs_map(), m_dynamic_reg_size_map(),
- m_reg_data_byte_size(0), m_finalized(false) {
+ const lldb_private::ArchSpec &arch) {
SetRegisterInfo(dict, arch);
}
-DynamicRegisterInfo::~DynamicRegisterInfo() {}
+DynamicRegisterInfo::DynamicRegisterInfo(DynamicRegisterInfo &&info) {
+ MoveFrom(std::move(info));
+}
+
+DynamicRegisterInfo &
+DynamicRegisterInfo::operator=(DynamicRegisterInfo &&info) {
+ MoveFrom(std::move(info));
+ return *this;
+}
+
+void DynamicRegisterInfo::MoveFrom(DynamicRegisterInfo &&info) {
+ m_regs = std::move(info.m_regs);
+ m_sets = std::move(info.m_sets);
+ m_set_reg_nums = std::move(info.m_set_reg_nums);
+ m_set_names = std::move(info.m_set_names);
+ m_value_regs_map = std::move(info.m_value_regs_map);
+ m_invalidate_regs_map = std::move(info.m_invalidate_regs_map);
+ m_dynamic_reg_size_map = std::move(info.m_dynamic_reg_size_map);
+
+ m_reg_data_byte_size = info.m_reg_data_byte_size;
+ m_finalized = info.m_finalized;
+
+ if (m_finalized) {
+ const size_t num_sets = m_sets.size();
+ for (size_t set = 0; set < num_sets; ++set)
+ m_sets[set].registers = m_set_reg_nums[set].data();
+ }
+
+ info.Clear();
+}
size_t
DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
@@ -44,13 +66,9 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
if (dict.GetValueForKeyAsArray("sets", sets)) {
const uint32_t num_sets = sets->GetSize();
for (uint32_t i = 0; i < num_sets; ++i) {
- llvm::StringRef set_name_str;
ConstString set_name;
- if (sets->GetItemAtIndexAsString(i, set_name_str))
- set_name.SetString(set_name_str);
- if (set_name) {
- RegisterSet new_set = {set_name.AsCString(), NULL, 0, NULL};
- m_sets.push_back(new_set);
+ if (sets->GetItemAtIndexAsString(i, set_name) && !set_name.IsEmpty()) {
+ m_sets.push_back({ set_name.AsCString(), NULL, 0, NULL });
} else {
Clear();
printf("error: register sets must have valid names\n");
@@ -59,6 +77,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
}
m_set_reg_nums.resize(m_sets.size());
}
+
StructuredData::Array *regs = nullptr;
if (!dict.GetValueForKeyAsArray("registers", regs))
return 0;
@@ -76,8 +95,8 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
return 0;
}
- // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint'
- // , 'format':'hex' , 'set': 0, 'ehframe' : 2,
+ // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16,
+ // 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2,
// 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
RegisterInfo reg_info;
std::vector<uint32_t> value_regs;
@@ -102,14 +121,11 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
const ByteOrder byte_order = arch.GetByteOrder();
if (reg_info.byte_offset == UINT32_MAX) {
- // No offset for this register, see if the register has a value expression
- // which indicates this register is part of another register. Value
- // expressions
- // are things like "rax[31:0]" which state that the current register's
- // value
- // is in a concrete register "rax" in bits 31:0. If there is a value
- // expression
- // we can calculate the offset
+ // No offset for this register, see if the register has a value
+ // expression which indicates this register is part of another register.
+ // Value expressions are things like "rax[31:0]" which state that the
+ // current register's value is in a concrete register "rax" in bits 31:0.
+ // If there is a value expression we can calculate the offset
bool success = false;
llvm::StringRef slice_str;
if (reg_info_dict->GetValueForKeyAsString("slice", slice_str, nullptr)) {
@@ -141,7 +157,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
ConstString containing_reg_name(reg_name_str);
- RegisterInfo *containing_reg_info =
+ const RegisterInfo *containing_reg_info =
GetRegisterInfo(containing_reg_name);
if (containing_reg_info) {
const uint32_t max_bit = containing_reg_info->byte_size * 8;
@@ -210,7 +226,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
ConstString composite_reg_name;
if (composite_reg_list->GetItemAtIndexAsString(
composite_idx, composite_reg_name, nullptr)) {
- RegisterInfo *composite_reg_info =
+ const RegisterInfo *composite_reg_info =
GetRegisterInfo(composite_reg_name);
if (composite_reg_info) {
composite_offset = std::min(composite_offset,
@@ -286,7 +302,8 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
llvm::StringRef format_str;
if (reg_info_dict->GetValueForKeyAsString("format", format_str, nullptr)) {
- if (Args::StringToFormat(format_str.str().c_str(), reg_info.format, NULL)
+ if (OptionArgParser::ToFormat(format_str.str().c_str(), reg_info.format,
+ NULL)
.Fail()) {
Clear();
printf("error: invalid 'format' value in register dictionary\n");
@@ -349,7 +366,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict,
uint64_t invalidate_reg_num;
if (invalidate_reg_list->GetItemAtIndexAsString(
idx, invalidate_reg_name)) {
- RegisterInfo *invalidate_reg_info =
+ const RegisterInfo *invalidate_reg_info =
GetRegisterInfo(invalidate_reg_name);
if (invalidate_reg_info) {
m_invalidate_regs_map[i].push_back(
@@ -437,7 +454,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
for (size_t set = 0; set < num_sets; ++set) {
assert(m_sets.size() == m_set_reg_nums.size());
m_sets[set].num_registers = m_set_reg_nums[set].size();
- m_sets[set].registers = &m_set_reg_nums[set][0];
+ m_sets[set].registers = m_set_reg_nums[set].data();
}
// sort and unique all value registers and make sure each is terminated with
@@ -492,8 +509,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
}
// sort and unique all invalidate registers and make sure each is terminated
- // with
- // LLDB_INVALID_REGNUM
+ // with LLDB_INVALID_REGNUM
for (reg_to_regs_map::iterator pos = m_invalidate_regs_map.begin(),
end = m_invalidate_regs_map.end();
pos != end; ++pos) {
@@ -517,8 +533,8 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
m_regs[i].invalidate_regs = NULL;
}
- // Check if we need to automatically set the generic registers in case
- // they weren't set
+ // Check if we need to automatically set the generic registers in case they
+ // weren't set
bool generic_regs_specified = false;
for (const auto &reg : m_regs) {
if (reg.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
@@ -730,11 +746,11 @@ void DynamicRegisterInfo::Dump() const {
}
}
-lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(
- const lldb_private::ConstString &reg_name) {
+const lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo(
+ const lldb_private::ConstString &reg_name) const {
for (auto &reg_info : m_regs) {
- // We can use pointer comparison since we used a ConstString to set
- // the "name" member in AddRegister()
+ // We can use pointer comparison since we used a ConstString to set the
+ // "name" member in AddRegister()
if (reg_info.name == reg_name.GetCString()) {
return &reg_info;
}
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index 228acfbed4ee..acb3e3eb8a84 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -23,12 +23,18 @@
class DynamicRegisterInfo {
public:
- DynamicRegisterInfo();
+ DynamicRegisterInfo() = default;
DynamicRegisterInfo(const lldb_private::StructuredData::Dictionary &dict,
const lldb_private::ArchSpec &arch);
- virtual ~DynamicRegisterInfo();
+ virtual ~DynamicRegisterInfo() = default;
+
+ DynamicRegisterInfo(DynamicRegisterInfo &) = delete;
+ void operator=(DynamicRegisterInfo &) = delete;
+
+ DynamicRegisterInfo(DynamicRegisterInfo &&info);
+ DynamicRegisterInfo &operator=(DynamicRegisterInfo &&info);
size_t SetRegisterInfo(const lldb_private::StructuredData::Dictionary &dict,
const lldb_private::ArchSpec &arch);
@@ -75,8 +81,10 @@ protected:
typedef std::vector<uint8_t> dwarf_opcode;
typedef std::map<uint32_t, dwarf_opcode> dynamic_reg_size_map;
- lldb_private::RegisterInfo *
- GetRegisterInfo(const lldb_private::ConstString &reg_name);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfo(const lldb_private::ConstString &reg_name) const;
+
+ void MoveFrom(DynamicRegisterInfo &&info);
reg_collection m_regs;
set_collection m_sets;
@@ -85,9 +93,8 @@ protected:
reg_to_regs_map m_value_regs_map;
reg_to_regs_map m_invalidate_regs_map;
dynamic_reg_size_map m_dynamic_reg_size_map;
- size_t m_reg_data_byte_size; // The number of bytes required to store all
- // registers
- bool m_finalized;
+ size_t m_reg_data_byte_size = 0u; // The number of bytes required to store
+ // all registers
+ bool m_finalized = false;
};
-
#endif // lldb_DynamicRegisterInfo_h_
diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h
index 363ba2669637..7675a95246a7 100644
--- a/source/Plugins/Process/Utility/HistoryThread.h
+++ b/source/Plugins/Process/Utility/HistoryThread.h
@@ -29,13 +29,13 @@ namespace lldb_private {
//----------------------------------------------------------------------
/// @class HistoryThread HistoryThread.h "HistoryThread.h"
-/// @brief A thread object representing a backtrace from a previous point in the
+/// A thread object representing a backtrace from a previous point in the
/// process execution
///
/// This subclass of Thread is used to provide a backtrace from earlier in
/// process execution. It is given a backtrace list of pc addresses and
-/// optionally a stop_id of when those pc addresses were collected, and it will
-/// create stack frames for them.
+/// optionally a stop_id of when those pc addresses were collected, and it
+/// will create stack frames for them.
//----------------------------------------------------------------------
class HistoryThread : public lldb_private::Thread {
diff --git a/source/Plugins/Process/Utility/InstructionUtils.h b/source/Plugins/Process/Utility/InstructionUtils.h
index e422a96200c8..186d525ce499 100644
--- a/source/Plugins/Process/Utility/InstructionUtils.h
+++ b/source/Plugins/Process/Utility/InstructionUtils.h
@@ -10,6 +10,9 @@
#ifndef lldb_InstructionUtils_h_
#define lldb_InstructionUtils_h_
+#include <cassert>
+#include <cstdint>
+
// Common utilities for manipulating instruction bit fields.
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h b/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h
new file mode 100644
index 000000000000..ff57464be2de
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwinConstants.h
@@ -0,0 +1,26 @@
+//===-- RegisterContextDarwinConstants.h ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_REGISTERCONTEXTDARWINCONSTANTS_H
+#define LLDB_REGISTERCONTEXTDARWINCONSTANTS_H
+
+namespace lldb_private {
+
+/// Constants returned by various RegisterContextDarwin_*** functions.
+#ifndef KERN_SUCCESS
+#define KERN_SUCCESS 0
+#endif
+
+#ifndef KERN_INVALID_ARGUMENT
+#define KERN_INVALID_ARGUMENT 4
+#endif
+
+} // namespace lldb_private
+
+#endif // LLDB_REGISTERCONTEXTDARWINCONSTANTS_H
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 64a697ff53c8..5d9ff02fafdd 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -7,13 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__APPLE__)
-
#include "RegisterContextDarwin_arm.h"
-
-// C Includes
-#include <mach/mach_types.h>
-#include <mach/thread_act.h>
+#include "RegisterContextDarwinConstants.h"
// C++ Includes
// Other libraries and framework includes
@@ -34,7 +29,7 @@
#endif
// Project includes
-#include "ARM_DWARF_Registers.h"
+#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
#include "llvm/ADT/STLExtras.h"
@@ -968,9 +963,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
@@ -1510,7 +1505,7 @@ uint32_t RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber(
}
uint32_t RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints() {
-#if defined(__arm__)
+#if defined(__APPLE__) && defined(__arm__)
// Set the init value to something that will let us know that we need to
// autodetect how many breakpoints are supported dynamically...
static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX;
@@ -1642,7 +1637,7 @@ bool RegisterContextDarwin_arm::ClearHardwareBreakpoint(uint32_t hw_index) {
}
uint32_t RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints() {
-#if defined(__arm__)
+#if defined(__APPLE__) && defined(__arm__)
// Set the init value to something that will let us know that we need to
// autodetect how many watchpoints are supported dynamically...
static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
@@ -1766,5 +1761,3 @@ bool RegisterContextDarwin_arm::ClearHardwareWatchpoint(uint32_t hw_index) {
}
return false;
}
-
-#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index 344c08965fad..03ce7ef9f524 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -8,14 +8,8 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__APPLE__)
-
#include "RegisterContextDarwin_arm64.h"
-
-// C Includes
-#include <mach/mach_types.h>
-#include <mach/thread_act.h>
-#include <sys/sysctl.h>
+#include "RegisterContextDarwinConstants.h"
// C++ Includes
// Other libraries and framework includes
@@ -39,7 +33,7 @@
#endif
// Project includes
-#include "ARM64_DWARF_Registers.h"
+#include "Utility/ARM64_DWARF_Registers.h"
using namespace lldb;
using namespace lldb_private;
@@ -149,9 +143,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
@@ -299,8 +293,9 @@ int RegisterContextDarwin_arm64::WriteRegisterSet(uint32_t set) {
void RegisterContextDarwin_arm64::LogDBGRegisters(Log *log, const DBG &dbg) {
if (log) {
for (uint32_t i = 0; i < 16; i++)
- log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8llx, 0x%8.8llx } WVR%-2u/WCR%-2u "
- "= { 0x%8.8llx, 0x%8.8llx }",
+ log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64
+ " } WVR%-2u/WCR%-2u "
+ "= { 0x%8.8" PRIu64 ", 0x%8.8" PRIu64 " }",
i, i, dbg.bvr[i], dbg.bcr[i], i, i, dbg.wvr[i], dbg.wcr[i]);
}
}
@@ -921,7 +916,7 @@ uint32_t RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber(
}
uint32_t RegisterContextDarwin_arm64::NumSupportedHardwareWatchpoints() {
-#if defined(__arm64__) || defined(__aarch64__)
+#if defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__))
// autodetect how many watchpoints are supported dynamically...
static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
if (g_num_supported_hw_watchpoints == UINT32_MAX) {
@@ -1043,5 +1038,3 @@ bool RegisterContextDarwin_arm64::ClearHardwareWatchpoint(uint32_t hw_index) {
}
return false;
}
-
-#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index c818fad9ac0e..24414211d9aa 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -147,9 +147,9 @@ enum {
sizeof(RegisterContextDarwin_i386::FPU))
// These macros will auto define the register name, alt name, register size,
-// register offset, encoding, format and native register. This ensures that
-// the register state structures are defined correctly and have the correct
-// sizes and offsets.
+// register offset, encoding, format and native register. This ensures that the
+// register state structures are defined correctly and have the correct sizes
+// and offsets.
#define DEFINE_GPR(reg, alt) \
#reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *) NULL)->reg), \
GPR_OFFSET(reg), eEncodingUint, eFormatHex
@@ -464,9 +464,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
@@ -680,8 +680,7 @@ bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info,
case fpu_stmm6:
case fpu_stmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes() must be used for these
- // registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
//::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes,
//10);
return false;
@@ -695,8 +694,7 @@ bool RegisterContextDarwin_i386::ReadRegister(const RegisterInfo *reg_info,
case fpu_xmm6:
case fpu_xmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes()
- // must be used for these registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
//::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes,
//16);
return false;
@@ -799,8 +797,7 @@ bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info,
case fpu_stmm6:
case fpu_stmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes()
- // must be used for these registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
::memcpy(fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(),
value.GetByteSize());
return false;
@@ -814,8 +811,7 @@ bool RegisterContextDarwin_i386::WriteRegister(const RegisterInfo *reg_info,
case fpu_xmm6:
case fpu_xmm7:
// These values don't fit into scalar types,
- // RegisterContext::ReadRegisterBytes()
- // must be used for these registers
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
::memcpy(fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(),
value.GetByteSize());
return false;
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 50e7292f86b1..ecad8240b294 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -165,9 +165,9 @@ enum ehframe_dwarf_regnums {
sizeof(RegisterContextDarwin_x86_64::FPU))
// These macros will auto define the register name, alt name, register size,
-// register offset, encoding, format and native register. This ensures that
-// the register state structures are defined correctly and have the correct
-// sizes and offsets.
+// register offset, encoding, format and native register. This ensures that the
+// register state structures are defined correctly and have the correct sizes
+// and offsets.
#define DEFINE_GPR(reg, alt) \
#reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *) NULL)->reg), \
GPR_OFFSET(reg), eEncodingUint, eFormatHex
@@ -525,9 +525,9 @@ const size_t k_num_fpu_registers = llvm::array_lengthof(g_fpu_regnums);
const size_t k_num_exc_registers = llvm::array_lengthof(g_exc_regnums);
//----------------------------------------------------------------------
-// Register set definitions. The first definitions at register set index
-// of zero is for all registers, followed by other registers sets. The
-// register information for the all register set need not be filled in.
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
//----------------------------------------------------------------------
static const RegisterSet g_reg_sets[] = {
{
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 5435a02433ab..ba9a8071bcfb 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -104,8 +104,7 @@ bool RegisterContextLLDB::IsUnwindPlanValidForCurrentPC(
}
// Initialize a RegisterContextLLDB which is the first frame of a stack -- the
-// zeroth frame or currently
-// executing frame.
+// zeroth frame or currently executing frame.
void RegisterContextLLDB::InitializeZerothFrame() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
@@ -131,25 +130,26 @@ void RegisterContextLLDB::InitializeZerothFrame() {
// Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
// this will strip bit zero in case we read a PC from memory or from the LR.
// (which would be a no-op in frame 0 where we get it from the register set,
- // but still a good idea to make the call here for other ABIs that may exist.)
+ // but still a good idea to make the call here for other ABIs that may
+ // exist.)
ABI *abi = process->GetABI().get();
if (abi)
current_pc = abi->FixCodeAddress(current_pc);
- // Initialize m_current_pc, an Address object, based on current_pc, an addr_t.
+ // Initialize m_current_pc, an Address object, based on current_pc, an
+ // addr_t.
m_current_pc.SetLoadAddress(current_pc, &process->GetTarget());
// If we don't have a Module for some reason, we're not going to find
- // symbol/function information - just
- // stick in some reasonable defaults and hope we can unwind past this frame.
+ // symbol/function information - just stick in some reasonable defaults and
+ // hope we can unwind past this frame.
ModuleSP pc_module_sp(m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp) {
UnwindLogMsg("using architectural default unwind method");
}
// We require either a symbol or function in the symbols context to be
- // successfully
- // filled in or this context is of no use to us.
+ // successfully filled in or this context is of no use to us.
const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
if (pc_module_sp.get() && (pc_module_sp->ResolveSymbolContextForAddress(
m_current_pc, resolve_scope, m_sym_ctx) &
@@ -180,18 +180,17 @@ void RegisterContextLLDB::InitializeZerothFrame() {
}
// If we were able to find a symbol/function, set addr_range to the bounds of
- // that symbol/function.
- // else treat the current pc value as the start_pc and record no offset.
+ // that symbol/function. else treat the current pc value as the start_pc and
+ // record no offset.
if (addr_range.GetBaseAddress().IsValid()) {
m_start_pc = addr_range.GetBaseAddress();
if (m_current_pc.GetSection() == m_start_pc.GetSection()) {
m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
} else if (m_current_pc.GetModule() == m_start_pc.GetModule()) {
- // This means that whatever symbol we kicked up isn't really correct
- // --- we should not cross section boundaries ... We really should NULL
- // out
- // the function/symbol in this case unless there is a bad assumption
- // here due to inlined functions?
+ // This means that whatever symbol we kicked up isn't really correct ---
+ // we should not cross section boundaries ... We really should NULL out
+ // the function/symbol in this case unless there is a bad assumption here
+ // due to inlined functions?
m_current_offset =
m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress();
}
@@ -266,8 +265,7 @@ void RegisterContextLLDB::InitializeZerothFrame() {
}
// Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the
-// RegisterContextLLDB "below" it
-// to provide things like its current pc value.
+// RegisterContextLLDB "below" it to provide things like its current pc value.
void RegisterContextLLDB::InitializeNonZerothFrame() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
@@ -333,8 +331,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end);
// If we don't have a Module for some reason, we're not going to find
- // symbol/function information - just
- // stick in some reasonable defaults and hope we can unwind past this frame.
+ // symbol/function information - just stick in some reasonable defaults and
+ // hope we can unwind past this frame.
ModuleSP pc_module_sp(m_current_pc.GetModule());
if (!m_current_pc.IsValid() || !pc_module_sp) {
UnwindLogMsg("using architectural default unwind method");
@@ -345,12 +343,10 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
if (process->GetLoadAddressPermissions(pc, permissions) &&
(permissions & ePermissionsExecutable) == 0) {
// If this is the second frame off the stack, we may have unwound the
- // first frame
- // incorrectly. But using the architecture default unwind plan may get us
- // back on
- // track -- albeit possibly skipping a real frame. Give this frame a
- // clearly-invalid
- // pc and see if we can get any further.
+ // first frame incorrectly. But using the architecture default unwind
+ // plan may get us back on track -- albeit possibly skipping a real
+ // frame. Give this frame a clearly-invalid pc and see if we can get any
+ // further.
if (GetNextFrame().get() && GetNextFrame()->IsValid() &&
GetNextFrame()->IsFrameZero()) {
UnwindLogMsg("had a pc of 0x%" PRIx64 " which is not in executable "
@@ -359,8 +355,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
(uint64_t)pc);
m_frame_type = eSkipFrame;
} else {
- // anywhere other than the second frame, a non-executable pc means we're
- // off in the weeds -- stop now.
+ // anywhere other than the second frame, a non-executable pc means
+ // we're off in the weeds -- stop now.
m_frame_type = eNotAValidFrame;
UnwindLogMsg("pc is in a non-executable section of memory and this "
"isn't the 2nd frame in the stack walk.");
@@ -399,8 +395,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
// m_cfa should point into the stack memory; if we can query memory
- // region permissions,
- // see if the memory is allocated & readable.
+ // region permissions, see if the memory is allocated & readable.
if (process->GetLoadAddressPermissions(m_cfa, permissions) &&
(permissions & ePermissionsReadable) == 0) {
m_frame_type = eNotAValidFrame;
@@ -435,19 +430,18 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
bool resolve_tail_call_address = false; // m_current_pc can be one past the
// address range of the function...
- // If the saved pc does not point to a function/symbol because it is
- // beyond the bounds of the correct function and there's no symbol there,
- // we do *not* want ResolveSymbolContextForAddress to back up the pc by 1,
- // because then we might not find the correct unwind information later.
- // Instead, let ResolveSymbolContextForAddress fail, and handle the case
- // via decr_pc_and_recompute_addr_range below.
+ // If the saved pc does not point to a function/symbol because it is beyond
+ // the bounds of the correct function and there's no symbol there, we do
+ // *not* want ResolveSymbolContextForAddress to back up the pc by 1, because
+ // then we might not find the correct unwind information later. Instead, let
+ // ResolveSymbolContextForAddress fail, and handle the case via
+ // decr_pc_and_recompute_addr_range below.
const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress(
m_current_pc, resolve_scope, m_sym_ctx, resolve_tail_call_address);
// We require either a symbol or function in the symbols context to be
- // successfully
- // filled in or this context is of no use to us.
+ // successfully filled in or this context is of no use to us.
if (resolve_scope & resolved_scope) {
m_sym_ctx_valid = true;
}
@@ -476,8 +470,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
decr_pc_and_recompute_addr_range = true;
// Or if we're in the middle of the stack (and not "above" an asynchronous
- // event like sigtramp),
- // and our "current" pc is the start of a function...
+ // event like sigtramp), and our "current" pc is the start of a function...
if (GetNextFrame()->m_frame_type != eTrapHandlerFrame &&
GetNextFrame()->m_frame_type != eDebuggerFrame &&
(!m_sym_ctx_valid ||
@@ -488,9 +481,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
// We need to back up the pc by 1 byte and re-search for the Symbol to handle
- // the case where the "saved pc"
- // value is pointing to the next function, e.g. if a function ends with a CALL
- // instruction.
+ // the case where the "saved pc" value is pointing to the next function, e.g.
+ // if a function ends with a CALL instruction.
// FIXME this may need to be an architectural-dependent behavior; if so we'll
// need to add a member function
// to the ABI plugin and consult that.
@@ -516,9 +508,9 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
GetSymbolOrFunctionName(m_sym_ctx).AsCString(""));
}
- // If we were able to find a symbol/function, set addr_range_ptr to the bounds
- // of that symbol/function.
- // else treat the current pc value as the start_pc and record no offset.
+ // If we were able to find a symbol/function, set addr_range_ptr to the
+ // bounds of that symbol/function. else treat the current pc value as the
+ // start_pc and record no offset.
if (addr_range.GetBaseAddress().IsValid()) {
m_start_pc = addr_range.GetBaseAddress();
m_current_offset = pc - m_start_pc.GetLoadAddress(&process->GetTarget());
@@ -553,9 +545,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
RegisterKind row_register_kind = eRegisterKindGeneric;
// Try to get by with just the fast UnwindPlan if possible - the full
- // UnwindPlan may be expensive to get
- // (e.g. if we have to parse the entire eh_frame section of an ObjectFile for
- // the first time.)
+ // UnwindPlan may be expensive to get (e.g. if we have to parse the entire
+ // eh_frame section of an ObjectFile for the first time.)
if (m_fast_unwind_plan_sp &&
m_fast_unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
@@ -616,16 +607,14 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
bool RegisterContextLLDB::CheckIfLoopingStack() {
// If we have a bad stack setup, we can get the same CFA value multiple times
- // -- or even
- // more devious, we can actually oscillate between two CFA values. Detect that
- // here and
- // break out to avoid a possible infinite loop in lldb trying to unwind the
- // stack.
- // To detect when we have the same CFA value multiple times, we compare the
+ // -- or even more devious, we can actually oscillate between two CFA values.
+ // Detect that here and break out to avoid a possible infinite loop in lldb
+ // trying to unwind the stack. To detect when we have the same CFA value
+ // multiple times, we compare the
// CFA of the current
// frame with the 2nd next frame because in some specail case (e.g. signal
- // hanlders, hand
- // written assembly without ABI compiance) we can have 2 frames with the same
+ // hanlders, hand written assembly without ABI compiance) we can have 2
+ // frames with the same
// CFA (in theory we
// can have arbitrary number of frames with the same CFA, but more then 2 is
// very very unlikely)
@@ -734,15 +723,12 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer)
- // so the pc is 0x0
- // in the zeroth frame, we need to use the "unwind at first instruction" arch
- // default UnwindPlan
- // Also, if this Process can report on memory region attributes, any
- // non-executable region means
- // we jumped through a bad function pointer - handle the same way as 0x0.
- // Note, if we have a symbol context & a symbol, we don't want to follow this
- // code path. This is
- // for jumping to memory regions without any information available.
+ // so the pc is 0x0 in the zeroth frame, we need to use the "unwind at first
+ // instruction" arch default UnwindPlan Also, if this Process can report on
+ // memory region attributes, any non-executable region means we jumped
+ // through a bad function pointer - handle the same way as 0x0. Note, if we
+ // have a symbol context & a symbol, we don't want to follow this code path.
+ // This is for jumping to memory regions without any information available.
if ((!m_sym_ctx_valid ||
(m_sym_ctx.function == NULL && m_sym_ctx.symbol == NULL)) &&
@@ -780,12 +766,10 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// No FuncUnwinders available for this pc (stripped function symbols, lldb
- // could not augment its
- // function table with another source, like LC_FUNCTION_STARTS or eh_frame in
- // ObjectFileMachO).
- // See if eh_frame or the .ARM.exidx tables have unwind information for this
- // address, else fall
- // back to the architectural default unwind.
+ // could not augment its function table with another source, like
+ // LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO). See if eh_frame or the
+ // .ARM.exidx tables have unwind information for this address, else fall back
+ // to the architectural default unwind.
if (!func_unwinders_sp) {
m_frame_type = eNormalFrame;
@@ -793,7 +777,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
!m_current_pc.IsValid())
return arch_default_unwind_plan_sp;
- // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
+ // Even with -fomit-frame-pointer, we can try eh_frame to get back on
+ // track.
DWARFCallFrameInfo *eh_frame =
pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo();
if (eh_frame) {
@@ -819,11 +804,10 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// If we're in _sigtramp(), unwinding past this frame requires special
- // knowledge. On Mac OS X this knowledge
- // is properly encoded in the eh_frame section, so prefer that if available.
- // On other platforms we may need to provide a platform-specific UnwindPlan
- // which encodes the details of
- // how to unwind out of sigtramp.
+ // knowledge. On Mac OS X this knowledge is properly encoded in the eh_frame
+ // section, so prefer that if available. On other platforms we may need to
+ // provide a platform-specific UnwindPlan which encodes the details of how to
+ // unwind out of sigtramp.
if (m_frame_type == eTrapHandlerFrame && process) {
m_fast_unwind_plan_sp.reset();
unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(
@@ -835,24 +819,19 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame
- // even when it's frame zero
- // This comes up if we have hand-written functions in a Module and
- // hand-written eh_frame. The assembly
- // instruction inspection may fail and the eh_frame CFI were probably written
- // with some care to do the
- // right thing. It'd be nice if there was a way to ask the eh_frame directly
- // if it is asynchronous
- // (can be trusted at every instruction point) or synchronous (the normal case
- // - only at call sites).
+ // even when it's frame zero This comes up if we have hand-written functions
+ // in a Module and hand-written eh_frame. The assembly instruction
+ // inspection may fail and the eh_frame CFI were probably written with some
+ // care to do the right thing. It'd be nice if there was a way to ask the
+ // eh_frame directly if it is asynchronous (can be trusted at every
+ // instruction point) or synchronous (the normal case - only at call sites).
// But there is not.
if (process && process->GetDynamicLoader() &&
process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo(m_sym_ctx)) {
// We must specifically call the GetEHFrameUnwindPlan() method here --
- // normally we would
- // call GetUnwindPlanAtCallSite() -- because CallSite may return an unwind
- // plan sourced from
- // either eh_frame (that's what we intend) or compact unwind (this won't
- // work)
+ // normally we would call GetUnwindPlanAtCallSite() -- because CallSite may
+ // return an unwind plan sourced from either eh_frame (that's what we
+ // intend) or compact unwind (this won't work)
unwind_plan_sp = func_unwinders_sp->GetEHFrameUnwindPlan(
process->GetTarget(), m_current_offset_backed_up_one);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
@@ -871,22 +850,16 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress(m_current_pc)) {
if (unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
// We probably have an UnwindPlan created by inspecting assembly
- // instructions. The
- // assembly profilers work really well with compiler-generated functions
- // but hand-
- // written assembly can be problematic. We set the eh_frame based unwind
- // plan as our
- // fallback unwind plan if instruction emulation doesn't work out even
- // for non call
- // sites if it is available and use the architecture default unwind plan
- // if it is
+ // instructions. The assembly profilers work really well with compiler-
+ // generated functions but hand- written assembly can be problematic.
+ // We set the eh_frame based unwind plan as our fallback unwind plan if
+ // instruction emulation doesn't work out even for non call sites if it
+ // is available and use the architecture default unwind plan if it is
// not available. The eh_frame unwind plan is more reliable even on non
- // call sites
- // then the architecture default plan and for hand written assembly code
- // it is often
- // written in a way that it valid at all location what helps in the most
- // common
- // cases when the instruction emulation fails.
+ // call sites then the architecture default plan and for hand written
+ // assembly code it is often written in a way that it valid at all
+ // location what helps in the most common cases when the instruction
+ // emulation fails.
UnwindPlanSP call_site_unwind_plan =
func_unwinders_sp->GetUnwindPlanAtCallSite(
process->GetTarget(), m_current_offset_backed_up_one);
@@ -919,9 +892,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// We'd prefer to use an UnwindPlan intended for call sites when we're at a
- // call site but if we've
- // struck out on that, fall back to using the non-call-site assembly
- // inspection UnwindPlan if possible.
+ // call site but if we've struck out on that, fall back to using the non-
+ // call-site assembly inspection UnwindPlan if possible.
if (process) {
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite(
process->GetTarget(), m_thread, m_current_offset_backed_up_one);
@@ -929,19 +901,14 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
if (unwind_plan_sp &&
unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolNo) {
// We probably have an UnwindPlan created by inspecting assembly
- // instructions. The assembly
- // profilers work really well with compiler-generated functions but hand-
- // written assembly
- // can be problematic. We set the eh_frame based unwind plan as our fallback
- // unwind plan if
+ // instructions. The assembly profilers work really well with compiler-
+ // generated functions but hand- written assembly can be problematic. We
+ // set the eh_frame based unwind plan as our fallback unwind plan if
// instruction emulation doesn't work out even for non call sites if it is
- // available and use
- // the architecture default unwind plan if it is not available. The eh_frame
- // unwind plan is
- // more reliable even on non call sites then the architecture default plan
- // and for hand
- // written assembly code it is often written in a way that it valid at all
- // location what
+ // available and use the architecture default unwind plan if it is not
+ // available. The eh_frame unwind plan is more reliable even on non call
+ // sites then the architecture default plan and for hand written assembly
+ // code it is often written in a way that it valid at all location what
// helps in the most common cases when the instruction emulation fails.
UnwindPlanSP call_site_unwind_plan =
func_unwinders_sp->GetUnwindPlanAtCallSite(
@@ -963,8 +930,8 @@ UnwindPlanSP RegisterContextLLDB::GetFullUnwindPlanForFrame() {
}
// If we're on the first instruction of a function, and we have an
- // architectural default UnwindPlan
- // for the initial instruction of a function, use that.
+ // architectural default UnwindPlan for the initial instruction of a
+ // function, use that.
if (m_current_offset_backed_up_one == 0) {
unwind_plan_sp =
func_unwinders_sp->GetUnwindPlanArchitectureDefaultAtFunctionEntry(
@@ -1115,12 +1082,10 @@ bool RegisterContextLLDB::IsValid() const {
}
// After the final stack frame in a stack walk we'll get one invalid
-// (eNotAValidFrame) stack frame --
-// one past the end of the stack walk. But higher-level code will need to tell
-// the differnece between
-// "the unwind plan below this frame failed" versus "we successfully completed
-// the stack walk" so
-// this method helps to disambiguate that.
+// (eNotAValidFrame) stack frame -- one past the end of the stack walk. But
+// higher-level code will need to tell the differnece between "the unwind plan
+// below this frame failed" versus "we successfully completed the stack walk"
+// so this method helps to disambiguate that.
bool RegisterContextLLDB::IsTrapHandlerFrame() const {
return m_frame_type == eTrapHandlerFrame;
@@ -1129,12 +1094,10 @@ bool RegisterContextLLDB::IsTrapHandlerFrame() const {
// A skip frame is a bogus frame on the stack -- but one where we're likely to
// find a real frame farther
// up the stack if we keep looking. It's always the second frame in an unwind
-// (i.e. the first frame after
-// frame zero) where unwinding can be the trickiest. Ideally we'll mark up this
-// frame in some way so the
-// user knows we're displaying bad data and we may have skipped one frame of
-// their real program in the
-// process of getting back on track.
+// (i.e. the first frame after frame zero) where unwinding can be the
+// trickiest. Ideally we'll mark up this frame in some way so the user knows
+// we're displaying bad data and we may have skipped one frame of their real
+// program in the process of getting back on track.
bool RegisterContextLLDB::IsSkipFrame() const {
return m_frame_type == eSkipFrame;
@@ -1231,8 +1194,8 @@ RegisterContextLLDB::SavedLocationForRegister(
RegisterNumber return_address_reg;
// If we're fetching the saved pc and this UnwindPlan defines a
- // ReturnAddress register (e.g. lr on arm),
- // look for the return address register number in the UnwindPlan's row.
+ // ReturnAddress register (e.g. lr on arm), look for the return address
+ // register number in the UnwindPlan's row.
if (pc_regnum.IsValid() && pc_regnum == regnum &&
m_full_unwind_plan_sp->GetReturnAddressRegister() !=
LLDB_INVALID_REGNUM) {
@@ -1272,10 +1235,8 @@ RegisterContextLLDB::SavedLocationForRegister(
}
// This is frame 0 and we're retrieving the PC and it's saved in a Return
- // Address register and
- // it hasn't been saved anywhere yet -- that is, it's still live in the
- // actual register.
- // Handle this specially.
+ // Address register and it hasn't been saved anywhere yet -- that is,
+ // it's still live in the actual register. Handle this specially.
if (have_unwindplan_regloc == false && return_address_reg.IsValid() &&
IsFrameZero()) {
@@ -1298,22 +1259,18 @@ RegisterContextLLDB::SavedLocationForRegister(
}
// If this architecture stores the return address in a register (it
- // defines a Return Address register)
- // and we're on a non-zero stack frame and the Full UnwindPlan says that
- // the pc is stored in the
+ // defines a Return Address register) and we're on a non-zero stack frame
+ // and the Full UnwindPlan says that the pc is stored in the
// RA registers (e.g. lr on arm), then we know that the full unwindplan is
// not trustworthy -- this
// is an impossible situation and the instruction emulation code has
- // likely been misled.
- // If this stack frame meets those criteria, we need to throw away the
- // Full UnwindPlan that the
- // instruction emulation came up with and fall back to the architecture's
- // Default UnwindPlan so
- // the stack walk can get past this point.
+ // likely been misled. If this stack frame meets those criteria, we need
+ // to throw away the Full UnwindPlan that the instruction emulation came
+ // up with and fall back to the architecture's Default UnwindPlan so the
+ // stack walk can get past this point.
// Special note: If the Full UnwindPlan was generated from the compiler,
- // don't second-guess it
- // when we're at a call site location.
+ // don't second-guess it when we're at a call site location.
// arch_default_ra_regnum is the return address register # in the Full
// UnwindPlan register numbering
@@ -1376,11 +1333,10 @@ RegisterContextLLDB::SavedLocationForRegister(
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
if (have_unwindplan_regloc == false) {
- // If the UnwindPlan failed to give us an unwind location for this register,
- // we may be able to fall back
- // to some ABI-defined default. For example, some ABIs allow to determine
- // the caller's SP via the CFA.
- // Also, the ABI may set volatile registers to the undefined state.
+ // If the UnwindPlan failed to give us an unwind location for this
+ // register, we may be able to fall back to some ABI-defined default. For
+ // example, some ABIs allow to determine the caller's SP via the CFA. Also,
+ // the ABI may set volatile registers to the undefined state.
ABI *abi = process ? process->GetABI().get() : NULL;
if (abi) {
const RegisterInfo *reg_info =
@@ -1558,24 +1514,19 @@ RegisterContextLLDB::SavedLocationForRegister(
// TryFallbackUnwindPlan() -- this method is a little tricky.
//
// When this is called, the frame above -- the caller frame, the "previous"
-// frame --
-// is invalid or bad.
+// frame -- is invalid or bad.
//
-// Instead of stopping the stack walk here, we'll try a different UnwindPlan and
-// see
-// if we can get a valid frame above us.
+// Instead of stopping the stack walk here, we'll try a different UnwindPlan
+// and see if we can get a valid frame above us.
//
// This most often happens when an unwind plan based on assembly instruction
-// inspection
-// is not correct -- mostly with hand-written assembly functions or functions
-// where the
-// stack frame is set up "out of band", e.g. the kernel saved the register
-// context and
-// then called an asynchronous trap handler like _sigtramp.
+// inspection is not correct -- mostly with hand-written assembly functions or
+// functions where the stack frame is set up "out of band", e.g. the kernel
+// saved the register context and then called an asynchronous trap handler like
+// _sigtramp.
//
// Often in these cases, if we just do a dumb stack walk we'll get past this
-// tricky
-// frame and our usual techniques can continue to be used.
+// tricky frame and our usual techniques can continue to be used.
bool RegisterContextLLDB::TryFallbackUnwindPlan() {
if (m_fallback_unwind_plan_sp.get() == nullptr)
@@ -1591,15 +1542,13 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
}
// If a compiler generated unwind plan failed, trying the arch default
- // unwindplan
- // isn't going to do any better.
+ // unwindplan isn't going to do any better.
if (m_full_unwind_plan_sp->GetSourcedFromCompiler() == eLazyBoolYes)
return false;
- // Get the caller's pc value and our own CFA value.
- // Swap in the fallback unwind plan, re-fetch the caller's pc value and CFA
- // value.
- // If they're the same, then the fallback unwind plan provides no benefit.
+ // Get the caller's pc value and our own CFA value. Swap in the fallback
+ // unwind plan, re-fetch the caller's pc value and CFA value. If they're the
+ // same, then the fallback unwind plan provides no benefit.
RegisterNumber pc_regnum(m_thread, eRegisterKindGeneric,
LLDB_REGNUM_GENERIC_PC);
@@ -1622,23 +1571,18 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
}
// This is a tricky wrinkle! If SavedLocationForRegister() detects a really
- // impossible
- // register location for the full unwind plan, it may call
- // ForceSwitchToFallbackUnwindPlan()
- // which in turn replaces the full unwindplan with the fallback... in short,
- // we're done,
- // we're using the fallback UnwindPlan.
- // We checked if m_fallback_unwind_plan_sp was nullptr at the top -- the only
- // way it
- // became nullptr since then is via SavedLocationForRegister().
+ // impossible register location for the full unwind plan, it may call
+ // ForceSwitchToFallbackUnwindPlan() which in turn replaces the full
+ // unwindplan with the fallback... in short, we're done, we're using the
+ // fallback UnwindPlan. We checked if m_fallback_unwind_plan_sp was nullptr
+ // at the top -- the only way it became nullptr since then is via
+ // SavedLocationForRegister().
if (m_fallback_unwind_plan_sp.get() == nullptr)
return true;
// Switch the full UnwindPlan to be the fallback UnwindPlan. If we decide
- // this isn't
- // working, we need to restore.
- // We'll also need to save & restore the value of the m_cfa ivar. Save is
- // down below a bit in 'old_cfa'.
+ // this isn't working, we need to restore. We'll also need to save & restore
+ // the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'.
UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
addr_t old_cfa = m_cfa;
@@ -2049,10 +1993,9 @@ bool RegisterContextLLDB::ReadPC(addr_t &pc) {
// A pc value of 0 or 1 is impossible in the middle of the stack -- it
// indicates the end of a stack walk.
// On the currently executing frame (or such a frame interrupted
- // asynchronously by sigtramp et al) this may
- // occur if code has jumped through a NULL pointer -- we want to be able to
- // unwind past that frame to help
- // find the bug.
+ // asynchronously by sigtramp et al) this may occur if code has jumped
+ // through a NULL pointer -- we want to be able to unwind past that frame
+ // to help find the bug.
ProcessSP process_sp (m_thread.GetProcess());
if (process_sp)
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index 2d24bdaed2cd..77c1bea34851 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -19,7 +19,7 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/StreamString.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -139,8 +139,8 @@ bool RegisterContextMacOSXFrameBackchain::ReadRegister(
bool RegisterContextMacOSXFrameBackchain::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
- // Not supported yet. We could easily add support for this by remembering
- // the address of each entry (it would need to be part of the cursor)
+ // Not supported yet. We could easily add support for this by remembering the
+ // address of each entry (it would need to be part of the cursor)
return false;
}
@@ -154,10 +154,10 @@ bool RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues(
bool RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues(
const lldb::DataBufferSP &data_sp) {
- // Since this class doesn't respond to "ReadAllRegisterValues()", it must
- // not have been the one that saved all the register values. So we just let
- // the thread's register context (the register context for frame zero) do
- // the writing.
+ // Since this class doesn't respond to "ReadAllRegisterValues()", it must not
+ // have been the one that saved all the register values. So we just let the
+ // thread's register context (the register context for frame zero) do the
+ // writing.
return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
}
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
index 8f0dfd2a5b50..76189ea781de 100644
--- a/source/Plugins/Process/Utility/RegisterContextMemory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -32,9 +32,9 @@ RegisterContextMemory::RegisterContextMemory(Thread &thread,
addr_t reg_data_addr)
: RegisterContext(thread, concrete_frame_idx), m_reg_infos(reg_infos),
m_reg_valid(), m_reg_data(), m_reg_data_addr(reg_data_addr) {
- // Resize our vector of bools to contain one bool for every register.
- // We will use these boolean values to know when a register value
- // is valid in m_reg_data.
+ // Resize our vector of bools to contain one bool for every register. We will
+ // use these boolean values to know when a register value is valid in
+ // m_reg_data.
const size_t num_regs = reg_infos.GetNumRegisters();
assert(num_regs > 0);
m_reg_valid.resize(num_regs);
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index bb3509330eec..352e251e3b64 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,7 +21,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_arm.h"
using namespace lldb;
@@ -107,11 +107,6 @@ RegisterContextPOSIX_arm::RegisterContextPOSIX_arm(
}
::memset(&m_fpr, 0, sizeof m_fpr);
-
- // elf-core yet to support ReadFPR()
- lldb::ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_arm::~RegisterContextPOSIX_arm() {}
@@ -142,8 +137,8 @@ size_t RegisterContextPOSIX_arm::GetGPRSize() {
const lldb_private::RegisterInfo *RegisterContextPOSIX_arm::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -199,8 +194,8 @@ bool RegisterContextPOSIX_arm::IsRegisterSetAvailable(size_t set_index) {
return set_index < k_num_register_sets;
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_arm::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index 89384c8f5190..3ff93cde2347 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,7 +21,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_arm64.h"
using namespace lldb;
@@ -126,11 +126,6 @@ RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64(
}
::memset(&m_fpr, 0, sizeof m_fpr);
-
- // elf-core yet to support ReadFPR()
- lldb::ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_arm64::~RegisterContextPOSIX_arm64() {}
@@ -162,8 +157,8 @@ size_t RegisterContextPOSIX_arm64::GetGPRSize() {
const lldb_private::RegisterInfo *
RegisterContextPOSIX_arm64::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -219,8 +214,8 @@ bool RegisterContextPOSIX_arm64::IsRegisterSetAvailable(size_t set_index) {
return set_index < k_num_register_sets;
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_arm64::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
index 6a55947ba5c2..98d1e6fa8817 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,11 +21,10 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_mips64.h"
#include "RegisterContextFreeBSD_mips64.h"
#include "RegisterContextLinux_mips64.h"
-#include "RegisterContextLinux_mips.h"
+#include "RegisterContextLinux_mips.h"
using namespace lldb_private;
using namespace lldb;
@@ -59,11 +59,6 @@ RegisterContextPOSIX_mips64::RegisterContextPOSIX_mips64(
static_cast<uint32_t>(m_registers_count[gpr_registers_count] +
m_registers_count[fpr_registers_count] +
m_registers_count[msa_registers_count]));
-
- // elf-core yet to support ReadFPR()
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_mips64::~RegisterContextPOSIX_mips64() {}
@@ -92,8 +87,8 @@ size_t RegisterContextPOSIX_mips64::GetGPRSize() {
const RegisterInfo *RegisterContextPOSIX_mips64::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -172,8 +167,8 @@ bool RegisterContextPOSIX_mips64::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_mips64::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = m_num_registers;
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
index c2b73e226165..9f0552539723 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -21,7 +22,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_powerpc.h"
using namespace lldb_private;
@@ -95,11 +95,6 @@ RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(
RegisterInfoInterface *register_info)
: RegisterContext(thread, concrete_frame_idx) {
m_register_info_ap.reset(register_info);
-
- // elf-core yet to support ReadFPR()
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc() {}
@@ -129,8 +124,8 @@ size_t RegisterContextPOSIX_powerpc::GetGPRSize() {
const RegisterInfo *RegisterContextPOSIX_powerpc::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -181,8 +176,8 @@ bool RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_powerpc::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
index de410f063b53..41ae5ec6b51a 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -20,7 +21,6 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Compiler.h"
-#include "Plugins/Process/elf-core/ProcessElfCore.h"
#include "RegisterContextPOSIX_ppc64le.h"
using namespace lldb_private;
@@ -117,10 +117,6 @@ RegisterContextPOSIX_ppc64le::RegisterContextPOSIX_ppc64le(
RegisterInfoInterface *register_info)
: RegisterContext(thread, concrete_frame_idx) {
m_register_info_ap.reset(register_info);
-
- ProcessSP base = CalculateProcess();
- if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
- return;
}
void RegisterContextPOSIX_ppc64le::InvalidateAllRegisters() {}
@@ -146,8 +142,8 @@ size_t RegisterContextPOSIX_ppc64le::GetGPRSize() {
const RegisterInfo *RegisterContextPOSIX_ppc64le::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -198,8 +194,8 @@ bool RegisterContextPOSIX_ppc64le::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_ppc64le::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
index b3365ee2f098..662ac38405ef 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
@@ -174,8 +174,8 @@ lldb::ByteOrder RegisterContextPOSIX_s390x::GetByteOrder() {
return byte_order;
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index 41cec8add987..d2a06e1b7897 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -414,8 +414,8 @@ size_t RegisterContextPOSIX_x86::GetFXSAVEOffset() {
const RegisterInfo *RegisterContextPOSIX_x86::GetRegisterInfo() {
// Commonly, this method is overridden and g_register_infos is copied and
- // specialized.
- // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+ // specialized. So, use GetRegisterInfo() rather than g_register_infos in
+ // this scope.
return m_register_info_ap->GetRegisterInfo();
}
@@ -531,8 +531,8 @@ bool RegisterContextPOSIX_x86::IsRegisterSetAvailable(size_t set_index) {
return (set_index < num_sets);
}
-// Used when parsing DWARF and EH frame information and any other
-// object file sections that contain register numbers in them.
+// Used when parsing DWARF and EH frame information and any other object file
+// sections that contain register numbers in them.
uint32_t RegisterContextPOSIX_x86::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h
index 1894b5368122..5d7ad89ad394 100644
--- a/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -19,7 +19,7 @@ namespace lldb_private {
///------------------------------------------------------------------------------
/// @class RegisterInfoInterface
///
-/// @brief RegisterInfo interface to patch RegisterInfo structure for archs.
+/// RegisterInfo interface to patch RegisterInfo structure for archs.
///------------------------------------------------------------------------------
class RegisterInfoInterface {
public:
diff --git a/source/Plugins/Process/Utility/RegisterInfos_ppc64.h b/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
new file mode 100644
index 000000000000..69f00e4ba885
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
@@ -0,0 +1,331 @@
+//===-- RegisterInfos_ppc64.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef DECLARE_REGISTER_INFOS_PPC64_STRUCT
+
+// C Includes
+#include <stddef.h>
+
+// Computes the offset of the given GPR_PPC64 in the user data area.
+#define GPR_PPC64_OFFSET(regname) (offsetof(GPR_PPC64, regname))
+#define FPR_PPC64_OFFSET(regname) (offsetof(FPR_PPC64, regname) \
+ + sizeof(GPR_PPC64))
+#define VMX_PPC64_OFFSET(regname) (offsetof(VMX_PPC64, regname) \
+ + sizeof(GPR_PPC64) + sizeof(FPR_PPC64))
+#define GPR_PPC64_SIZE(regname) (sizeof(((GPR_PPC64 *)NULL)->regname))
+
+#include "Utility/PPC64_DWARF_Registers.h"
+#include "lldb-ppc64-register-enums.h"
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR_PPC64(reg, alt, lldb_kind) \
+ { \
+ #reg, alt, GPR_PPC64_SIZE(reg), GPR_PPC64_OFFSET(reg), lldb::eEncodingUint,\
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_##reg##_ppc64, \
+ ppc64_dwarf::dwarf_##reg##_ppc64, \
+ lldb_kind, \
+ LLDB_INVALID_REGNUM, \
+ gpr_##reg##_ppc64 }, \
+ NULL, NULL, NULL, 0 \
+ }
+#define DEFINE_FPR_PPC64(reg, alt, lldb_kind) \
+ { \
+#reg, alt, 8, FPR_PPC64_OFFSET(reg), lldb::eEncodingIEEE754, \
+ lldb::eFormatFloat, \
+ {ppc64_dwarf::dwarf_##reg##_ppc64, \
+ ppc64_dwarf::dwarf_##reg##_ppc64, lldb_kind, LLDB_INVALID_REGNUM, \
+ fpr_##reg##_ppc64 }, \
+ NULL, NULL, NULL, 0 \
+ }
+#define DEFINE_VMX_PPC64(reg, lldb_kind) \
+ { \
+#reg, NULL, 16, VMX_PPC64_OFFSET(reg), lldb::eEncodingVector, \
+ lldb::eFormatVectorOfUInt32, \
+ {ppc64_dwarf::dwarf_##reg##_ppc64, \
+ ppc64_dwarf::dwarf_##reg##_ppc64, lldb_kind, LLDB_INVALID_REGNUM, \
+ vmx_##reg##_ppc64 }, \
+ NULL, NULL, NULL, 0 \
+ }
+
+// General purpose registers.
+// EH_Frame, Generic, Process Plugin
+#define PPC64_REGS \
+ DEFINE_GPR_PPC64(r0, NULL, LLDB_INVALID_REGNUM) \
+ , DEFINE_GPR_PPC64(r1, "sp", LLDB_REGNUM_GENERIC_SP), \
+ DEFINE_GPR_PPC64(r2, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r3, "arg1", LLDB_REGNUM_GENERIC_ARG1), \
+ DEFINE_GPR_PPC64(r4, "arg2", LLDB_REGNUM_GENERIC_ARG2), \
+ DEFINE_GPR_PPC64(r5, "arg3", LLDB_REGNUM_GENERIC_ARG3), \
+ DEFINE_GPR_PPC64(r6, "arg4", LLDB_REGNUM_GENERIC_ARG4), \
+ DEFINE_GPR_PPC64(r7, "arg5", LLDB_REGNUM_GENERIC_ARG5), \
+ DEFINE_GPR_PPC64(r8, "arg6", LLDB_REGNUM_GENERIC_ARG6), \
+ DEFINE_GPR_PPC64(r9, "arg7", LLDB_REGNUM_GENERIC_ARG7), \
+ DEFINE_GPR_PPC64(r10, "arg8", LLDB_REGNUM_GENERIC_ARG8), \
+ DEFINE_GPR_PPC64(r11, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r12, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r13, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r14, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r15, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r16, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r17, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r18, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r19, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r20, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r21, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r22, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r23, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r24, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r25, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r26, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r27, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r28, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r29, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r30, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(r31, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \
+ DEFINE_GPR_PPC64(msr, "msr", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(xer, "xer", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(lr, "lr", LLDB_REGNUM_GENERIC_RA), \
+ DEFINE_GPR_PPC64(ctr, "ctr", LLDB_INVALID_REGNUM), \
+ DEFINE_GPR_PPC64(pc, "pc", LLDB_REGNUM_GENERIC_PC), \
+ DEFINE_FPR_PPC64(f0, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f1, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f2, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f3, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f4, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f5, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f6, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f7, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f8, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f9, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f10, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f11, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f12, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f13, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f14, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f15, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f16, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f17, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f18, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f19, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f20, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f21, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f22, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f23, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f24, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f25, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f26, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f27, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f28, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f29, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f30, NULL, LLDB_INVALID_REGNUM), \
+ DEFINE_FPR_PPC64(f31, NULL, LLDB_INVALID_REGNUM), \
+ {"fpscr", \
+ NULL, \
+ 8, \
+ FPR_PPC64_OFFSET(fpscr), \
+ lldb::eEncodingUint, \
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_fpscr_ppc64, \
+ ppc64_dwarf::dwarf_fpscr_ppc64, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, fpr_fpscr_ppc64}, \
+ NULL, \
+ NULL, \
+ NULL, \
+ 0}, \
+ DEFINE_VMX_PPC64(vr0, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr1, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr2, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr3, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr4, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr5, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr6, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr7, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr8, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr9, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr10, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr11, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr12, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr13, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr14, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr15, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr16, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr17, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr18, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr19, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr20, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr21, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr22, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr23, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr24, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr25, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr26, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr27, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr28, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr29, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr30, LLDB_INVALID_REGNUM), \
+ DEFINE_VMX_PPC64(vr31, LLDB_INVALID_REGNUM), \
+ {"vscr", \
+ NULL, \
+ 4, \
+ VMX_PPC64_OFFSET(vscr), \
+ lldb::eEncodingUint, \
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_vscr_ppc64, ppc64_dwarf::dwarf_vscr_ppc64, \
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_ppc64}, \
+ NULL, \
+ NULL, \
+ NULL, \
+ 0}, \
+ {"vrsave", \
+ NULL, \
+ 4, \
+ VMX_PPC64_OFFSET(vrsave), \
+ lldb::eEncodingUint, \
+ lldb::eFormatHex, \
+ {ppc64_dwarf::dwarf_vrsave_ppc64, \
+ ppc64_dwarf::dwarf_vrsave_ppc64, LLDB_INVALID_REGNUM, \
+ LLDB_INVALID_REGNUM, vmx_vrsave_ppc64}, \
+ NULL, \
+ NULL, \
+ NULL, \
+ 0}, /* */
+
+typedef struct _GPR_PPC64 {
+ uint64_t r0;
+ uint64_t r1;
+ uint64_t r2;
+ uint64_t r3;
+ uint64_t r4;
+ uint64_t r5;
+ uint64_t r6;
+ uint64_t r7;
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ uint64_t r16;
+ uint64_t r17;
+ uint64_t r18;
+ uint64_t r19;
+ uint64_t r20;
+ uint64_t r21;
+ uint64_t r22;
+ uint64_t r23;
+ uint64_t r24;
+ uint64_t r25;
+ uint64_t r26;
+ uint64_t r27;
+ uint64_t r28;
+ uint64_t r29;
+ uint64_t r30;
+ uint64_t r31;
+ uint64_t cr;
+ uint64_t msr;
+ uint64_t xer;
+ uint64_t lr;
+ uint64_t ctr;
+ uint64_t pc;
+ uint64_t pad[3];
+} GPR_PPC64;
+
+typedef struct _FPR_PPC64 {
+ uint64_t f0;
+ uint64_t f1;
+ uint64_t f2;
+ uint64_t f3;
+ uint64_t f4;
+ uint64_t f5;
+ uint64_t f6;
+ uint64_t f7;
+ uint64_t f8;
+ uint64_t f9;
+ uint64_t f10;
+ uint64_t f11;
+ uint64_t f12;
+ uint64_t f13;
+ uint64_t f14;
+ uint64_t f15;
+ uint64_t f16;
+ uint64_t f17;
+ uint64_t f18;
+ uint64_t f19;
+ uint64_t f20;
+ uint64_t f21;
+ uint64_t f22;
+ uint64_t f23;
+ uint64_t f24;
+ uint64_t f25;
+ uint64_t f26;
+ uint64_t f27;
+ uint64_t f28;
+ uint64_t f29;
+ uint64_t f30;
+ uint64_t f31;
+ uint64_t fpscr;
+} FPR_PPC64;
+
+typedef struct _VMX_PPC64 {
+ uint32_t vr0[4];
+ uint32_t vr1[4];
+ uint32_t vr2[4];
+ uint32_t vr3[4];
+ uint32_t vr4[4];
+ uint32_t vr5[4];
+ uint32_t vr6[4];
+ uint32_t vr7[4];
+ uint32_t vr8[4];
+ uint32_t vr9[4];
+ uint32_t vr10[4];
+ uint32_t vr11[4];
+ uint32_t vr12[4];
+ uint32_t vr13[4];
+ uint32_t vr14[4];
+ uint32_t vr15[4];
+ uint32_t vr16[4];
+ uint32_t vr17[4];
+ uint32_t vr18[4];
+ uint32_t vr19[4];
+ uint32_t vr20[4];
+ uint32_t vr21[4];
+ uint32_t vr22[4];
+ uint32_t vr23[4];
+ uint32_t vr24[4];
+ uint32_t vr25[4];
+ uint32_t vr26[4];
+ uint32_t vr27[4];
+ uint32_t vr28[4];
+ uint32_t vr29[4];
+ uint32_t vr30[4];
+ uint32_t vr31[4];
+ uint32_t pad[2];
+ uint32_t vscr[2];
+ uint32_t vrsave;
+} VMX_PPC64;
+
+
+static lldb_private::RegisterInfo g_register_infos_ppc64[] = {
+ PPC64_REGS
+};
+
+static_assert((sizeof(g_register_infos_ppc64) /
+ sizeof(g_register_infos_ppc64[0])) ==
+ k_num_registers_ppc64,
+ "g_register_infos_powerpc64 has wrong number of register infos");
+
+#undef DEFINE_FPR_PPC64
+#undef DEFINE_GPR_PPC64
+#undef DEFINE_VMX_PPC64
+
+#endif // DECLARE_REGISTER_INFOS_PPC64_STRUCT
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 3e860874183c..3dbfe611e713 100644
--- a/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -356,8 +356,8 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
{
if (exc_sub_code == 5) {
- // On MacOSX, a SIGTRAP can signify that a process has called
- // exec, so we should check with our dynamic loader to verify.
+ // On MacOSX, a SIGTRAP can signify that a process has called exec,
+ // so we should check with our dynamic loader to verify.
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
@@ -403,10 +403,8 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (!exc_sub_code) {
// This looks like a plain trap.
// Have to check if there is a breakpoint here as well. When you
- // single-step onto a trap,
- // the single step stops you not to trap. Since we also do that
- // check below, let's just use
- // that logic.
+ // single-step onto a trap, the single step stops you not to trap.
+ // Since we also do that check below, let's just use that logic.
is_actual_breakpoint = true;
is_trace_if_actual_breakpoint_missing = true;
} else {
@@ -419,8 +417,8 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
(lldb::addr_t)exc_sub_code);
if (wp_sp && wp_sp->IsEnabled()) {
// Debugserver may piggyback the hardware index of the fired
- // watchpoint in the exception data.
- // Set the hardware index if that's the case.
+ // watchpoint in the exception data. Set the hardware index if
+ // that's the case.
if (exc_data_count >= 3)
wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
return StopInfo::CreateStopReasonWithWatchpointID(thread,
@@ -450,16 +448,15 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
{
// It's a watchpoint, then, if the exc_sub_code indicates a
- // known/enabled
- // data break address from our watchpoint list.
+ // known/enabled data break address from our watchpoint list.
lldb::WatchpointSP wp_sp;
if (target)
wp_sp = target->GetWatchpointList().FindByAddress(
(lldb::addr_t)exc_sub_code);
if (wp_sp && wp_sp->IsEnabled()) {
// Debugserver may piggyback the hardware index of the fired
- // watchpoint in the exception data.
- // Set the hardware index if that's the case.
+ // watchpoint in the exception data. Set the hardware index if
+ // that's the case.
if (exc_data_count >= 3)
wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
return StopInfo::CreateStopReasonWithWatchpointID(thread,
@@ -473,9 +470,9 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
is_actual_breakpoint = true;
is_trace_if_actual_breakpoint_missing = true;
} else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel
- // is currently returning this so accept it as
- // indicating a breakpoint until the kernel is
- // fixed
+ // is currently returning this so accept it
+ // as indicating a breakpoint until the
+ // kernel is fixed
{
is_actual_breakpoint = true;
is_trace_if_actual_breakpoint_missing = true;
@@ -493,16 +490,15 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
{
// It's a watchpoint, then, if the exc_sub_code indicates a
- // known/enabled
- // data break address from our watchpoint list.
+ // known/enabled data break address from our watchpoint list.
lldb::WatchpointSP wp_sp;
if (target)
wp_sp = target->GetWatchpointList().FindByAddress(
(lldb::addr_t)exc_sub_code);
if (wp_sp && wp_sp->IsEnabled()) {
// Debugserver may piggyback the hardware index of the fired
- // watchpoint in the exception data.
- // Set the hardware index if that's the case.
+ // watchpoint in the exception data. Set the hardware index if
+ // that's the case.
if (exc_data_count >= 3)
wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
return StopInfo::CreateStopReasonWithWatchpointID(thread,
@@ -514,8 +510,7 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
return StopInfo::CreateStopReasonToTrace(thread);
}
// It looks like exc_sub_code has the 4 bytes of the instruction that
- // triggered the
- // exception, i.e. our breakpoint opcode
+ // triggered the exception, i.e. our breakpoint opcode
is_actual_breakpoint = exc_code == 1;
break;
}
@@ -534,23 +529,21 @@ StopInfoSP StopInfoMachException::CreateStopReasonWithMachException(
if (process_sp)
bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
if (bp_site_sp && bp_site_sp->IsEnabled()) {
- // Update the PC if we were asked to do so, but only do
- // so if we find a breakpoint that we know about cause
- // this could be a trap instruction in the code
+ // Update the PC if we were asked to do so, but only do so if we find
+ // a breakpoint that we know about cause this could be a trap
+ // instruction in the code
if (pc_decrement > 0 && adjust_pc_if_needed)
reg_ctx_sp->SetPC(pc);
// If the breakpoint is for this thread, then we'll report the hit,
- // but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
+ // but if it is for another thread, we can just report no reason. We
+ // don't need to worry about stepping over the breakpoint here, that
// will be taken care of when the thread resumes and notices that
- // there's a breakpoint under the pc.
- // If we have an operating system plug-in, we might have set a thread
- // specific breakpoint using the
+ // there's a breakpoint under the pc. If we have an operating system
+ // plug-in, we might have set a thread specific breakpoint using the
// operating system thread ID, so we can't make any assumptions about
- // the thread ID so we must always
- // report the breakpoint regardless of the thread.
+ // the thread ID so we must always report the breakpoint regardless
+ // of the thread.
if (bp_site_sp->ValidForThisThread(&thread) ||
thread.GetProcess()->GetOperatingSystem() != NULL)
return StopInfo::CreateStopReasonWithBreakpointSiteID(
diff --git a/source/Plugins/Process/Utility/ThreadMemory.cpp b/source/Plugins/Process/Utility/ThreadMemory.cpp
index 5ff928c69e59..0c7c195815a4 100644
--- a/source/Plugins/Process/Utility/ThreadMemory.cpp
+++ b/source/Plugins/Process/Utility/ThreadMemory.cpp
@@ -62,7 +62,7 @@ ThreadMemory::CreateRegisterContextForFrame(StackFrame *frame) {
reg_ctx_sp = GetRegisterContext();
} else {
Unwind *unwinder = GetUnwinder();
- if (unwinder)
+ if (unwinder != nullptr)
reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 2b34bddd90b2..55559f07f1e5 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -132,16 +132,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
// We want to detect an unwind that cycles erroneously and stop backtracing.
// Don't want this maximum unwind limit to be too low -- if you have a
- // backtrace
- // with an "infinitely recursing" bug, it will crash when the stack blows out
- // and the first 35,000 frames are uninteresting - it's the top most 5 frames
- // that
- // you actually care about. So you can't just cap the unwind at 10,000 or
- // something.
- // Realistically anything over around 200,000 is going to blow out the stack
- // space.
- // If we're still unwinding at that point, we're probably never going to
- // finish.
+ // backtrace with an "infinitely recursing" bug, it will crash when the stack
+ // blows out and the first 35,000 frames are uninteresting - it's the top
+ // most 5 frames that you actually care about. So you can't just cap the
+ // unwind at 10,000 or something. Realistically anything over around 200,000
+ // is going to blow out the stack space. If we're still unwinding at that
+ // point, we're probably never going to finish.
if (cur_idx > 300000) {
if (log)
log->Printf("%*sFrame %d unwound too many frames, assuming unwind has "
@@ -152,13 +148,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
if (reg_ctx_sp.get() == NULL) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -172,15 +167,13 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (!reg_ctx_sp->IsValid()) {
- // We failed to get a valid RegisterContext.
- // See if the regctx below this on the stack has a fallback unwind plan it
- // can use.
- // Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // We failed to get a valid RegisterContext. See if the regctx below this
+ // on the stack has a fallback unwind plan it can use. Subsequent calls to
+ // TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -195,13 +188,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (!reg_ctx_sp->GetCFA(cursor_sp->cfa)) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -216,27 +208,21 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa)) {
// On Mac OS X, the _sigtramp asynchronous signal trampoline frame may not
- // have
- // its (constructed) CFA aligned correctly -- don't do the abi alignment
- // check for
- // these.
+ // have its (constructed) CFA aligned correctly -- don't do the abi
+ // alignment check for these.
if (reg_ctx_sp->IsTrapHandlerFrame() == false) {
// See if we can find a fallback unwind plan for THIS frame. It may be
// that the UnwindPlan we're using for THIS frame was bad and gave us a
- // bad CFA.
- // If that's not it, then see if we can change the UnwindPlan for the
- // frame
- // below us ("NEXT") -- see if using that other UnwindPlan gets us a
- // better
- // unwind state.
+ // bad CFA. If that's not it, then see if we can change the UnwindPlan
+ // for the frame below us ("NEXT") -- see if using that other UnwindPlan
+ // gets us a better unwind state.
if (reg_ctx_sp->TryFallbackUnwindPlan() == false ||
reg_ctx_sp->GetCFA(cursor_sp->cfa) == false ||
abi->CallFrameAddressIsValid(cursor_sp->cfa) == false) {
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be
- // updated. Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of
+ // prev_frame still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -259,13 +245,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (!reg_ctx_sp->ReadPC(cursor_sp->start_pc)) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -280,13 +265,12 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
}
if (abi && !abi->CodeAddressIsValid(cursor_sp->start_pc)) {
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to
- // that and return
- // true. Subsequent calls to TryFallbackUnwindPlan() will return false.
+ // that and return true. Subsequent calls to TryFallbackUnwindPlan() will
+ // return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
- // reg_ctx_lldb_sp field of
- // prev_frame. However, cfa field of prev_frame still needs to be updated.
- // Hence updating it.
+ // reg_ctx_lldb_sp field of prev_frame. However, cfa field of prev_frame
+ // still needs to be updated. Hence updating it.
if (!(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
return nullptr;
@@ -320,13 +304,12 @@ void UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid(ABI *abi) {
CursorSP old_m_candidate_frame = m_candidate_frame;
// Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan
- // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also
- // update the cfa of Frame 0 (if required).
+ // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also update
+ // the cfa of Frame 0 (if required).
AddOneMoreFrame(abi);
- // Remove all the frames added by above function as the purpose of
- // using above function was just to check whether Unwinder of Frame 0
- // works or not.
+ // Remove all the frames added by above function as the purpose of using
+ // above function was just to check whether Unwinder of Frame 0 works or not.
for (uint32_t i = 1; i < m_frames.size(); i++)
m_frames.pop_back();
@@ -362,51 +345,44 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) {
m_frames.push_back(new_frame);
- // If we can get one more frame further then accept that we get back a correct
- // frame.
+ // If we can get one more frame further then accept that we get back a
+ // correct frame.
m_candidate_frame = GetOneMoreFrame(abi);
if (m_candidate_frame)
return true;
// We can't go further from the frame returned by GetOneMore frame. Lets try
- // to get a
- // different frame with using the fallback unwind plan.
+ // to get a different frame with using the fallback unwind plan.
if (!m_frames[m_frames.size() - 2]
->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// We don't have a valid fallback unwind plan. Accept the frame as it is.
- // This is a
- // valid situation when we are at the bottom of the stack.
+ // This is a valid situation when we are at the bottom of the stack.
return true;
}
// Remove the possibly incorrect frame from the frame list and try to add a
- // different one with
- // the newly selected fallback unwind plan.
+ // different one with the newly selected fallback unwind plan.
m_frames.pop_back();
CursorSP new_frame_v2 = GetOneMoreFrame(abi);
if (new_frame_v2 == nullptr) {
// We haven't got a new frame from the fallback unwind plan. Accept the
- // frame from the
- // original unwind plan. This is a valid situation when we are at the bottom
- // of the stack.
+ // frame from the original unwind plan. This is a valid situation when we
+ // are at the bottom of the stack.
m_frames.push_back(new_frame);
return true;
}
// Push the new frame to the list and try to continue from this frame. If we
- // can get a new frame
- // then accept it as the correct one.
+ // can get a new frame then accept it as the correct one.
m_frames.push_back(new_frame_v2);
m_candidate_frame = GetOneMoreFrame(abi);
if (m_candidate_frame) {
// If control reached here then TryFallbackUnwindPlan had succeeded for
- // Cursor::m_frames[m_frames.size() - 2].
- // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() -
- // 1] and a frame after that.
- // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was
- // already updated during TryFallbackUnwindPlan
- // call above. However, cfa field still needs to be updated. Hence updating
- // it here and then returning.
+ // Cursor::m_frames[m_frames.size() - 2]. It also succeeded to Unwind next
+ // 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that. For
+ // Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already
+ // updated during TryFallbackUnwindPlan call above. However, cfa field
+ // still needs to be updated. Hence updating it here and then returning.
if (!(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(
m_frames[m_frames.size() - 2]->cfa)))
return false;
@@ -414,8 +390,7 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) {
}
// The new frame hasn't helped in unwinding. Fall back to the original one as
- // the default unwind
- // plan is usually more reliable then the fallback one.
+ // the default unwind plan is usually more reliable then the fallback one.
m_frames.pop_back();
m_frames.push_back(new_frame);
return true;
@@ -486,10 +461,9 @@ bool UnwindLLDB::SearchForSavedLocationForRegister(
if (static_cast<size_t>(frame_num) >= m_frames.size())
return false;
- // Never interrogate more than one level while looking for the saved pc value.
- // If the value
- // isn't saved by frame_num, none of the frames lower on the stack will have a
- // useful value.
+ // Never interrogate more than one level while looking for the saved pc
+ // value. If the value isn't saved by frame_num, none of the frames lower on
+ // the stack will have a useful value.
if (pc_reg) {
UnwindLLDB::RegisterSearchResult result;
result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister(
@@ -505,8 +479,7 @@ bool UnwindLLDB::SearchForSavedLocationForRegister(
lldb_regnum, regloc);
// We descended down to the live register context aka stack frame 0 and are
- // reading the value
- // out of a live register.
+ // reading the value out of a live register.
if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound &&
regloc.type ==
UnwindLLDB::RegisterLocation::eRegisterInLiveRegisterContext) {
@@ -514,11 +487,9 @@ bool UnwindLLDB::SearchForSavedLocationForRegister(
}
// If we have unwind instructions saying that register N is saved in
- // register M in the middle of
- // the stack (and N can equal M here, meaning the register was not used in
- // this function), then
- // change the register number we're looking for to M and keep looking for a
- // concrete location
+ // register M in the middle of the stack (and N can equal M here, meaning
+ // the register was not used in this function), then change the register
+ // number we're looking for to M and keep looking for a concrete location
// down the stack, or an actual value from a live RegisterContext at frame
// 0.
if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound &&
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h
index 3f84649aa05f..3d1f85a3dec3 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -17,6 +17,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Unwind.h"
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
index d831011cb661..2115b4e179c0 100644
--- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
@@ -133,8 +133,8 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386(
if (addr_range_ptr) {
if (first_frame->GetFrameCodeAddress() ==
addr_range_ptr->GetBaseAddress()) {
- // We are at the first instruction, so we can recover the
- // previous PC by dereferencing the SP
+ // We are at the first instruction, so we can recover the previous PC
+ // by dereferencing the SP
lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
// Read the real second frame return address into frame.pc
if (first_frame_sp &&
@@ -224,8 +224,8 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64(
if (addr_range_ptr) {
if (first_frame->GetFrameCodeAddress() ==
addr_range_ptr->GetBaseAddress()) {
- // We are at the first instruction, so we can recover the
- // previous PC by dereferencing the SP
+ // We are at the first instruction, so we can recover the previous PC
+ // by dereferencing the SP
lldb::addr_t first_frame_sp = reg_ctx->GetSP(0);
// Read the real second frame return address into frame.pc
if (process->ReadMemory(first_frame_sp, &frame.pc, sizeof(frame.pc),
diff --git a/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h b/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h
new file mode 100644
index 000000000000..9ea81c00b666
--- /dev/null
+++ b/source/Plugins/Process/Utility/lldb-ppc64-register-enums.h
@@ -0,0 +1,139 @@
+//===-- lldb-ppc64-register-enums.h ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_ppc64_register_enums_h
+#define lldb_ppc64_register_enums_h
+
+// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)
+
+// ---------------------------------------------------------------------------
+// Internal codes for all ppc64 registers.
+// ---------------------------------------------------------------------------
+enum {
+ k_first_gpr_ppc64,
+ gpr_r0_ppc64 = k_first_gpr_ppc64,
+ gpr_r1_ppc64,
+ gpr_r2_ppc64,
+ gpr_r3_ppc64,
+ gpr_r4_ppc64,
+ gpr_r5_ppc64,
+ gpr_r6_ppc64,
+ gpr_r7_ppc64,
+ gpr_r8_ppc64,
+ gpr_r9_ppc64,
+ gpr_r10_ppc64,
+ gpr_r11_ppc64,
+ gpr_r12_ppc64,
+ gpr_r13_ppc64,
+ gpr_r14_ppc64,
+ gpr_r15_ppc64,
+ gpr_r16_ppc64,
+ gpr_r17_ppc64,
+ gpr_r18_ppc64,
+ gpr_r19_ppc64,
+ gpr_r20_ppc64,
+ gpr_r21_ppc64,
+ gpr_r22_ppc64,
+ gpr_r23_ppc64,
+ gpr_r24_ppc64,
+ gpr_r25_ppc64,
+ gpr_r26_ppc64,
+ gpr_r27_ppc64,
+ gpr_r28_ppc64,
+ gpr_r29_ppc64,
+ gpr_r30_ppc64,
+ gpr_r31_ppc64,
+ gpr_cr_ppc64,
+ gpr_msr_ppc64,
+ gpr_xer_ppc64,
+ gpr_lr_ppc64,
+ gpr_ctr_ppc64,
+ gpr_pc_ppc64,
+ k_last_gpr_ppc64 = gpr_pc_ppc64,
+
+ k_first_fpr_ppc64,
+ fpr_f0_ppc64 = k_first_fpr_ppc64,
+ fpr_f1_ppc64,
+ fpr_f2_ppc64,
+ fpr_f3_ppc64,
+ fpr_f4_ppc64,
+ fpr_f5_ppc64,
+ fpr_f6_ppc64,
+ fpr_f7_ppc64,
+ fpr_f8_ppc64,
+ fpr_f9_ppc64,
+ fpr_f10_ppc64,
+ fpr_f11_ppc64,
+ fpr_f12_ppc64,
+ fpr_f13_ppc64,
+ fpr_f14_ppc64,
+ fpr_f15_ppc64,
+ fpr_f16_ppc64,
+ fpr_f17_ppc64,
+ fpr_f18_ppc64,
+ fpr_f19_ppc64,
+ fpr_f20_ppc64,
+ fpr_f21_ppc64,
+ fpr_f22_ppc64,
+ fpr_f23_ppc64,
+ fpr_f24_ppc64,
+ fpr_f25_ppc64,
+ fpr_f26_ppc64,
+ fpr_f27_ppc64,
+ fpr_f28_ppc64,
+ fpr_f29_ppc64,
+ fpr_f30_ppc64,
+ fpr_f31_ppc64,
+ fpr_fpscr_ppc64,
+ k_last_fpr_ppc64 = fpr_fpscr_ppc64,
+
+ k_first_vmx_ppc64,
+ vmx_vr0_ppc64 = k_first_vmx_ppc64,
+ vmx_vr1_ppc64,
+ vmx_vr2_ppc64,
+ vmx_vr3_ppc64,
+ vmx_vr4_ppc64,
+ vmx_vr5_ppc64,
+ vmx_vr6_ppc64,
+ vmx_vr7_ppc64,
+ vmx_vr8_ppc64,
+ vmx_vr9_ppc64,
+ vmx_vr10_ppc64,
+ vmx_vr11_ppc64,
+ vmx_vr12_ppc64,
+ vmx_vr13_ppc64,
+ vmx_vr14_ppc64,
+ vmx_vr15_ppc64,
+ vmx_vr16_ppc64,
+ vmx_vr17_ppc64,
+ vmx_vr18_ppc64,
+ vmx_vr19_ppc64,
+ vmx_vr20_ppc64,
+ vmx_vr21_ppc64,
+ vmx_vr22_ppc64,
+ vmx_vr23_ppc64,
+ vmx_vr24_ppc64,
+ vmx_vr25_ppc64,
+ vmx_vr26_ppc64,
+ vmx_vr27_ppc64,
+ vmx_vr28_ppc64,
+ vmx_vr29_ppc64,
+ vmx_vr30_ppc64,
+ vmx_vr31_ppc64,
+ vmx_vscr_ppc64,
+ vmx_vrsave_ppc64,
+ k_last_vmx_ppc64 = vmx_vrsave_ppc64,
+
+ k_num_registers_ppc64,
+ k_num_gpr_registers_ppc64 = k_last_gpr_ppc64 - k_first_gpr_ppc64 + 1,
+ k_num_fpr_registers_ppc64 = k_last_fpr_ppc64 - k_first_fpr_ppc64 + 1,
+ k_num_vmx_registers_ppc64 = k_last_vmx_ppc64 - k_first_vmx_ppc64 + 1,
+};
+
+#endif // #ifndef lldb_ppc64_register_enums_h
diff --git a/source/Plugins/Process/Windows/Common/CMakeLists.txt b/source/Plugins/Process/Windows/Common/CMakeLists.txt
index 009a289bae39..092629086183 100644
--- a/source/Plugins/Process/Windows/Common/CMakeLists.txt
+++ b/source/Plugins/Process/Windows/Common/CMakeLists.txt
@@ -1,6 +1,3 @@
-include_directories(.)
-include_directories(../../Utility)
-
set(PROC_WINDOWS_COMMON_SOURCES
DebuggerThread.cpp
LocalDebugDelegate.cpp
diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
index ac9e65c3c108..ad43551a4c6d 100644
--- a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
+++ b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
@@ -112,8 +112,7 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) {
lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(
const ProcessLaunchInfo &launch_info) {
// Grab a shared_ptr reference to this so that we know it won't get deleted
- // until after the
- // thread routine has exited.
+ // until after the thread routine has exited.
std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
@@ -124,14 +123,11 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(
ProcessLauncherWindows launcher;
HostProcess process(launcher.LaunchProcess(launch_info, error));
// If we couldn't create the process, notify waiters immediately. Otherwise
- // enter the debug
- // loop and wait until we get the create process debug notification. Note
- // that if the process
- // was created successfully, we can throw away the process handle we got from
- // CreateProcess
- // because Windows will give us another (potentially more useful?) handle when
- // it sends us the
- // CREATE_PROCESS_DEBUG_EVENT.
+ // enter the debug loop and wait until we get the create process debug
+ // notification. Note that if the process was created successfully, we can
+ // throw away the process handle we got from CreateProcess because Windows
+ // will give us another (potentially more useful?) handle when it sends us
+ // the CREATE_PROCESS_DEBUG_EVENT.
if (error.Success())
DebugLoop();
else
@@ -143,8 +139,7 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(
lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(
lldb::pid_t pid, const ProcessAttachInfo &attach_info) {
// Grab a shared_ptr reference to this so that we know it won't get deleted
- // until after the
- // thread routine has exited.
+ // until after the thread routine has exited.
std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
@@ -157,11 +152,9 @@ lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(
return 0;
}
- // The attach was successful, enter the debug loop. From here on out, this is
- // no different than
- // a create process operation, so all the same comments in DebugLaunch should
- // apply from this
- // point out.
+ // The attach was successful, enter the debug loop. From here on out, this
+ // is no different than a create process operation, so all the same comments
+ // in DebugLaunch should apply from this point out.
DebugLoop();
return 0;
@@ -188,21 +181,25 @@ Status DebuggerThread::StopDebugging(bool terminate) {
lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle();
if (terminate) {
- // Initiate the termination before continuing the exception, so that the
- // next debug
- // event we get is the exit process event, and not some other event.
- BOOL terminate_suceeded = TerminateProcess(handle, 0);
- LLDB_LOG(log,
- "calling TerminateProcess({0}, 0) (inferior={1}), success={2}",
- handle, pid, terminate_suceeded);
+ if (handle != nullptr && handle != LLDB_INVALID_PROCESS) {
+ // Initiate the termination before continuing the exception, so that the
+ // next debug event we get is the exit process event, and not some other
+ // event.
+ BOOL terminate_suceeded = TerminateProcess(handle, 0);
+ LLDB_LOG(log,
+ "calling TerminateProcess({0}, 0) (inferior={1}), success={2}",
+ handle, pid, terminate_suceeded);
+ } else {
+ LLDB_LOG(log,
+ "NOT calling TerminateProcess because the inferior is not valid ({0}, 0) (inferior={1})",
+ handle, pid);
+ }
}
// If we're stuck waiting for an exception to continue (e.g. the user is at a
- // breakpoint
- // messing around in the debugger), continue it now. But only AFTER calling
- // TerminateProcess
- // to make sure that the very next call to WaitForDebugEvent is an exit
- // process event.
+ // breakpoint messing around in the debugger), continue it now. But only
+ // AFTER calling TerminateProcess to make sure that the very next call to
+ // WaitForDebugEvent is an exit process event.
if (m_active_exception.get()) {
LLDB_LOG(log, "masking active exception");
ContinueAsyncException(ExceptionResult::MaskException);
@@ -355,8 +352,7 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
}
// Don't perform any blocking operations while we're shutting down. That
- // will
- // cause TerminateProcess -> WaitForSingleObject to time out.
+ // will cause TerminateProcess -> WaitForSingleObject to time out.
return ExceptionResult::SendToApplication;
}
@@ -373,8 +369,8 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
m_exception_pred.SetValue(result, eBroadcastNever);
LLDB_LOG(log, "waiting for ExceptionPred != BreakInDebugger");
- m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger,
- result);
+ result = *m_exception_pred.WaitForValueNotEqualTo(
+ ExceptionResult::BreakInDebugger);
LLDB_LOG(log, "got ExceptionPred = {0}", (int)m_exception_pred.GetValue());
return result;
diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index a1c9cfaed41c..b14081f76617 100644
--- a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -77,8 +77,8 @@ std::string GetProcessExecutableName(DWORD pid) {
namespace lldb_private {
// We store a pointer to this class in the ProcessWindows, so that we don't
-// expose Windows-specific types and implementation details from a public header
-// file.
+// expose Windows-specific types and implementation details from a public
+// header file.
class ProcessWindowsData {
public:
ProcessWindowsData(bool stop_at_entry) : m_stop_at_entry(stop_at_entry) {
@@ -186,9 +186,9 @@ Status ProcessWindows::DoDetach(bool keep_stopped) {
StateType private_state;
{
// Acquire the lock only long enough to get the DebuggerThread.
- // StopDebugging() will trigger a call back into ProcessWindows which
- // will also acquire the lock. Thus we have to release the lock before
- // calling StopDebugging().
+ // StopDebugging() will trigger a call back into ProcessWindows which will
+ // also acquire the lock. Thus we have to release the lock before calling
+ // StopDebugging().
llvm::sys::ScopedLock lock(m_mutex);
private_state = GetPrivateState();
@@ -228,14 +228,22 @@ Status ProcessWindows::DoDetach(bool keep_stopped) {
Status ProcessWindows::DoLaunch(Module *exe_module,
ProcessLaunchInfo &launch_info) {
- // Even though m_session_data is accessed here, it is before a debugger thread
- // has been
- // kicked off. So there's no race conditions, and it shouldn't be necessary
- // to acquire
- // the mutex.
+ // Even though m_session_data is accessed here, it is before a debugger
+ // thread has been kicked off. So there's no race conditions, and it
+ // shouldn't be necessary to acquire the mutex.
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
Status result;
+
+ FileSpec working_dir = launch_info.GetWorkingDirectory();
+ namespace fs = llvm::sys::fs;
+ if (working_dir && (!working_dir.ResolvePath() ||
+ !fs::is_directory(working_dir.GetPath()))) {
+ result.SetErrorStringWithFormat("No such file or directory: %s",
+ working_dir.GetCString());
+ return result;
+ }
+
if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
StreamString stream;
stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can "
@@ -251,7 +259,6 @@ Status ProcessWindows::DoLaunch(Module *exe_module,
bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
m_session_data.reset(new ProcessWindowsData(stop_at_entry));
- SetPrivateState(eStateLaunching);
DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
m_session_data->m_debugger.reset(new DebuggerThread(delegate));
DebuggerThreadSP debugger = m_session_data->m_debugger;
@@ -276,12 +283,10 @@ Status ProcessWindows::DoLaunch(Module *exe_module,
launch_info.GetExecutableFile().GetPath());
// We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
- // private state
- // should already be set to eStateStopped as a result of hitting the initial
- // breakpoint. If
- // it was not set, the breakpoint should have already been resumed from and
- // the private state
- // should already be eStateRunning.
+ // private state should already be set to eStateStopped as a result of
+ // hitting the initial breakpoint. If it was not set, the breakpoint should
+ // have already been resumed from and the private state should already be
+ // eStateRunning.
launch_info.SetProcessID(process.GetProcessId());
SetID(process.GetProcessId());
@@ -322,12 +327,10 @@ ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid,
LLDB_LOG(log, "successfully attached to process with pid={0}", process_id);
// We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the
- // private state
- // should already be set to eStateStopped as a result of hitting the initial
- // breakpoint. If
- // it was not set, the breakpoint should have already been resumed from and
- // the private state
- // should already be eStateRunning.
+ // private state should already be set to eStateStopped as a result of
+ // hitting the initial breakpoint. If it was not set, the breakpoint should
+ // have already been resumed from and the private state should already be
+ // eStateRunning.
SetID(process.GetProcessId());
return error;
}
@@ -346,22 +349,35 @@ Status ProcessWindows::DoResume() {
ExceptionRecordSP active_exception =
m_session_data->m_debugger->GetActiveException().lock();
if (active_exception) {
- // Resume the process and continue processing debug events. Mask
- // the exception so that from the process's view, there is no
- // indication that anything happened.
+ // Resume the process and continue processing debug events. Mask the
+ // exception so that from the process's view, there is no indication that
+ // anything happened.
m_session_data->m_debugger->ContinueAsyncException(
ExceptionResult::MaskException);
}
LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize());
+ bool failed = false;
for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
auto thread = std::static_pointer_cast<TargetThreadWindows>(
m_thread_list.GetThreadAtIndex(i));
- thread->DoResume();
+ Status result = thread->DoResume();
+ if (result.Fail()) {
+ failed = true;
+ LLDB_LOG(
+ log,
+ "Trying to resume thread at index {0}, but failed with error {1}.",
+ i, result);
+ }
}
- SetPrivateState(eStateRunning);
+ if (failed) {
+ error.SetErrorString("ProcessWindows::DoResume failed");
+ return error;
+ } else {
+ SetPrivateState(eStateRunning);
+ }
} else {
LLDB_LOG(log, "error: process %I64u is in state %u. Returning...",
m_session_data->m_debugger->GetProcess().GetProcessId(),
@@ -376,10 +392,9 @@ Status ProcessWindows::DoDestroy() {
StateType private_state;
{
// Acquire this lock inside an inner scope, only long enough to get the
- // DebuggerThread.
- // StopDebugging() will trigger a call back into ProcessWindows which will
- // acquire the lock
- // again, so we need to not deadlock.
+ // DebuggerThread. StopDebugging() will trigger a call back into
+ // ProcessWindows which will acquire the lock again, so we need to not
+ // deadlock.
llvm::sys::ScopedLock lock(m_mutex);
private_state = GetPrivateState();
@@ -461,8 +476,9 @@ void ProcessWindows::RefreshStateAfterStop() {
m_session_data->m_debugger->GetActiveException();
ExceptionRecordSP active_exception = exception_record.lock();
if (!active_exception) {
- LLDB_LOG(log, "there is no active exception in process {0}. Why is the "
- "process stopped?",
+ LLDB_LOG(log,
+ "there is no active exception in process {0}. Why is the "
+ "process stopped?",
m_session_data->m_debugger->GetProcess().GetProcessId());
return;
}
@@ -479,8 +495,9 @@ void ProcessWindows::RefreshStateAfterStop() {
const uint64_t pc = register_context->GetPC();
BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
if (site && site->ValidForThisThread(stop_thread.get())) {
- LLDB_LOG(log, "Single-stepped onto a breakpoint in process {0} at "
- "address {1:x} with breakpoint site {2}",
+ LLDB_LOG(log,
+ "Single-stepped onto a breakpoint in process {0} at "
+ "address {1:x} with breakpoint site {2}",
m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
site->GetID());
stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
@@ -502,22 +519,25 @@ void ProcessWindows::RefreshStateAfterStop() {
BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
if (site) {
- LLDB_LOG(log, "detected breakpoint in process {0} at address {1:x} with "
- "breakpoint site {2}",
+ LLDB_LOG(log,
+ "detected breakpoint in process {0} at address {1:x} with "
+ "breakpoint site {2}",
m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
site->GetID());
if (site->ValidForThisThread(stop_thread.get())) {
- LLDB_LOG(log, "Breakpoint site {0} is valid for this thread ({1:x}), "
- "creating stop info.",
+ LLDB_LOG(log,
+ "Breakpoint site {0} is valid for this thread ({1:x}), "
+ "creating stop info.",
site->GetID(), stop_thread->GetID());
stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
*stop_thread, site->GetID());
register_context->SetPC(pc);
} else {
- LLDB_LOG(log, "Breakpoint site {0} is not valid for this thread, "
- "creating empty stop info.",
+ LLDB_LOG(log,
+ "Breakpoint site {0} is not valid for this thread, "
+ "creating empty stop info.",
site->GetID());
}
stop_thread->SetStopInfo(stop_info);
@@ -558,8 +578,8 @@ bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
ModuleSP exe_module_sp(target_sp->GetExecutableModule());
if (exe_module_sp.get())
return exe_module_sp->GetFileSpec().Exists();
- // However, if there is no executable module, we return true since we might be
- // preparing to attach.
+ // However, if there is no executable module, we return true since we might
+ // be preparing to attach.
return true;
}
@@ -589,8 +609,8 @@ bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list,
}
}
- // Also add all the threads that are new since the last time we broke into the
- // debugger.
+ // Also add all the threads that are new since the last time we broke into
+ // the debugger.
for (const auto &thread_info : m_session_data->m_new_threads) {
ThreadSP thread(new TargetThreadWindows(*this, thread_info.second));
thread->SetID(thread_info.first);
@@ -639,8 +659,13 @@ size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,
SIZE_T bytes_read = 0;
if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr,
buf, size, &bytes_read)) {
+ // Reading from the process can fail for a number of reasons - set the
+ // error code and make sure that the number of bytes read is set back to 0
+ // because in some scenarios the value of bytes_read returned from the API
+ // is garbage.
error.SetError(GetLastError(), eErrorTypeWin32);
LLDB_LOG(log, "reading failed with error: {0}", error);
+ bytes_read = 0;
}
return bytes_read;
}
@@ -699,11 +724,9 @@ Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
if (result == 0) {
if (::GetLastError() == ERROR_INVALID_PARAMETER) {
- // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an
- // address
- // past the highest accessible address. We should return a range from the
- // vm_addr
- // to LLDB_INVALID_ADDRESS
+ // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with
+ // an address past the highest accessible address. We should return a
+ // range from the vm_addr to LLDB_INVALID_ADDRESS
info.GetRange().SetRangeBase(vm_addr);
info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
info.SetReadable(MemoryRegionInfo::eNo);
@@ -713,8 +736,9 @@ Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
return error;
} else {
error.SetError(::GetLastError(), eErrorTypeWin32);
- LLDB_LOG(log, "VirtualQueryEx returned error {0} while getting memory "
- "region info for address {1:x}",
+ LLDB_LOG(log,
+ "VirtualQueryEx returned error {0} while getting memory "
+ "region info for address {1:x}",
error, vm_addr);
return error;
}
@@ -744,10 +768,8 @@ Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
info.SetMapped(MemoryRegionInfo::eYes);
} else {
// In the unmapped case we need to return the distance to the next block of
- // memory.
- // VirtualQueryEx nearly does that except that it gives the distance from
- // the start
- // of the page containing vm_addr.
+ // memory. VirtualQueryEx nearly does that except that it gives the
+ // distance from the start of the page containing vm_addr.
SYSTEM_INFO data;
GetSystemInfo(&data);
DWORD page_offset = vm_addr % data.dwPageSize;
@@ -757,8 +779,9 @@ Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
}
error.SetError(::GetLastError(), eErrorTypeWin32);
- LLDB_LOGV(log, "Memory region info for address {0}: readable={1}, "
- "executable={2}, writable={3}",
+ LLDB_LOGV(log,
+ "Memory region info for address {0}: readable={1}, "
+ "executable={2}, writable={3}",
vm_addr, info.GetReadable(), info.GetExecutable(),
info.GetWritable());
return error;
@@ -779,7 +802,7 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) {
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
- TargetSP target = m_target_sp.lock();
+ TargetSP target = CalculateTarget();
if (target) {
ModuleSP executable_module = target->GetExecutableModule();
ModuleList unloaded_modules;
@@ -825,10 +848,9 @@ void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
GetTarget().ModulesDidLoad(loaded_modules);
// Add the main executable module to the list of pending module loads. We
- // can't call
- // GetTarget().ModulesDidLoad() here because we still haven't returned from
- // DoLaunch() / DoAttach() yet
- // so the target may not have set the process instance to `this` yet.
+ // can't call GetTarget().ModulesDidLoad() here because we still haven't
+ // returned from DoLaunch() / DoAttach() yet so the target may not have set
+ // the process instance to `this` yet.
llvm::sys::ScopedLock lock(m_mutex);
const HostThreadWindows &wmain_thread =
debugger->GetMainThread().GetNativeThread();
@@ -845,15 +867,14 @@ ProcessWindows::OnDebugException(bool first_chance,
// FIXME: Without this check, occasionally when running the test suite there
// is
// an issue where m_session_data can be null. It's not clear how this could
- // happen
- // but it only surfaces while running the test suite. In order to properly
- // diagnose
- // this, we probably need to first figure allow the test suite to print out
- // full
- // lldb logs, and then add logging to the process plugin.
+ // happen but it only surfaces while running the test suite. In order to
+ // properly diagnose this, we probably need to first figure allow the test
+ // suite to print out full lldb logs, and then add logging to the process
+ // plugin.
if (!m_session_data) {
- LLDB_LOG(log, "Debugger thread reported exception {0:x} at address {1:x}, "
- "but there is no session.",
+ LLDB_LOG(log,
+ "Debugger thread reported exception {0:x} at address {1:x}, "
+ "but there is no session.",
record.GetExceptionCode(), record.GetExceptionAddress());
return ExceptionResult::SendToApplication;
}
@@ -887,8 +908,9 @@ ProcessWindows::OnDebugException(bool first_chance,
SetPrivateState(eStateStopped);
break;
default:
- LLDB_LOG(log, "Debugger thread reported exception {0:x} at address {1:x} "
- "(first_chance={2})",
+ LLDB_LOG(log,
+ "Debugger thread reported exception {0:x} at address {1:x} "
+ "(first_chance={2})",
record.GetExceptionCode(), record.GetExceptionAddress(),
first_chance);
// For non-breakpoints, give the application a chance to handle the
@@ -929,9 +951,8 @@ void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
lldb::addr_t module_addr) {
// Confusingly, there is no Target::AddSharedModule. Instead, calling
- // GetSharedModule() with
- // a new module will add it to the module list and return a corresponding
- // ModuleSP.
+ // GetSharedModule() with a new module will add it to the module list and
+ // return a corresponding ModuleSP.
Status error;
ModuleSP module = GetTarget().GetSharedModule(module_spec, &error);
bool load_addr_changed = false;
@@ -961,17 +982,16 @@ void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) {
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
if (m_session_data->m_initial_stop_received) {
- // This happened while debugging. Do we shutdown the debugging session, try
- // to continue, or do something else?
- LLDB_LOG(log, "Error {0} occurred during debugging. Unexpected behavior "
- "may result. {1}",
+ // This happened while debugging. Do we shutdown the debugging session,
+ // try to continue, or do something else?
+ LLDB_LOG(log,
+ "Error {0} occurred during debugging. Unexpected behavior "
+ "may result. {1}",
error.GetError(), error);
} else {
// If we haven't actually launched the process yet, this was an error
- // launching the
- // process. Set the internal error and signal the initial stop event so
- // that the DoLaunch
- // method wakes up and returns a failure.
+ // launching the process. Set the internal error and signal the initial
+ // stop event so that the DoLaunch method wakes up and returns a failure.
m_session_data->m_launch_error = error;
::SetEvent(m_session_data->m_initial_stop_event);
LLDB_LOG(
@@ -1001,9 +1021,9 @@ Status ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger,
}
// The Windows page protection bits are NOT independent masks that can be
-// bitwise-ORed together. For example, PAGE_EXECUTE_READ is not
-// (PAGE_EXECUTE | PAGE_READ). To test for an access type, it's necessary to
-// test for any of the bits that provide that access type.
+// bitwise-ORed together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE
+// | PAGE_READ). To test for an access type, it's necessary to test for any of
+// the bits that provide that access type.
bool ProcessWindows::IsPageReadable(uint32_t protect) {
return (protect & PAGE_NOACCESS) == 0;
}
diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
index a4d60303877e..3903280918cc 100644
--- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
+++ b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
@@ -16,10 +16,10 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
+#include "Plugins/Process/Utility/UnwindLLDB.h"
#include "ProcessWindows.h"
#include "ProcessWindowsLog.h"
#include "TargetThreadWindows.h"
-#include "UnwindLLDB.h"
#if defined(_WIN64)
#include "x64/RegisterContextWindows_x64.h"
@@ -33,7 +33,7 @@ using namespace lldb_private;
TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
const HostThread &thread)
: Thread(process, thread.GetNativeThread().GetThreadId()),
- m_host_thread(thread) {}
+ m_thread_reg_ctx_sp(), m_host_thread(thread) {}
TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
@@ -49,40 +49,53 @@ void TargetThreadWindows::DidStop() {}
RegisterContextSP TargetThreadWindows::GetRegisterContext() {
if (!m_reg_context_sp)
- m_reg_context_sp = CreateRegisterContextForFrameIndex(0);
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
return m_reg_context_sp;
}
RegisterContextSP
TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
- return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex());
-}
-
-RegisterContextSP
-TargetThreadWindows::CreateRegisterContextForFrameIndex(uint32_t idx) {
- if (!m_reg_context_sp) {
- ArchSpec arch = HostInfo::GetArchitecture();
- switch (arch.GetMachine()) {
- case llvm::Triple::x86:
+ RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0) {
+ if (!m_thread_reg_ctx_sp) {
+ ArchSpec arch = HostInfo::GetArchitecture();
+ switch (arch.GetMachine()) {
+ case llvm::Triple::x86:
#if defined(_WIN64)
-// FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
+ // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
+ LLDB_LOG(log, "This is a Wow64 process, we should create a "
+ "RegisterContextWindows_Wow64, but we don't.");
#else
- m_reg_context_sp.reset(new RegisterContextWindows_x86(*this, idx));
+ m_thread_reg_ctx_sp.reset(
+ new RegisterContextWindows_x86(*this, concrete_frame_idx));
#endif
- break;
- case llvm::Triple::x86_64:
+ break;
+ case llvm::Triple::x86_64:
#if defined(_WIN64)
- m_reg_context_sp.reset(new RegisterContextWindows_x64(*this, idx));
+ m_thread_reg_ctx_sp.reset(
+ new RegisterContextWindows_x64(*this, concrete_frame_idx));
#else
-// LLDB is 32-bit, but the target process is 64-bit. We probably can't debug
-// this.
+ LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit.");
#endif
- default:
- break;
+ default:
+ break;
+ }
}
+ reg_ctx_sp = m_thread_reg_ctx_sp;
+ } else {
+ Unwind *unwinder = GetUnwinder();
+ if (unwinder != nullptr)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
- return m_reg_context_sp;
+
+ return reg_ctx_sp;
}
bool TargetThreadWindows::CalculateStopInfo() {
@@ -93,16 +106,16 @@ bool TargetThreadWindows::CalculateStopInfo() {
Unwind *TargetThreadWindows::GetUnwinder() {
// FIXME: Implement an unwinder based on the Windows unwinder exposed through
// DIA SDK.
- if (m_unwinder_ap.get() == NULL)
+ if (!m_unwinder_ap)
m_unwinder_ap.reset(new UnwindLLDB(*this));
return m_unwinder_ap.get();
}
-bool TargetThreadWindows::DoResume() {
+Status TargetThreadWindows::DoResume() {
StateType resume_state = GetTemporaryResumeState();
StateType current_state = GetState();
if (resume_state == current_state)
- return true;
+ return Status();
if (resume_state == eStateStepping) {
uint32_t flags_index =
@@ -118,8 +131,17 @@ bool TargetThreadWindows::DoResume() {
DWORD previous_suspend_count = 0;
HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
do {
+ // ResumeThread returns -1 on error, or the thread's *previous* suspend
+ // count on success. This means that the return value is 1 when the thread
+ // was restarted. Note that DWORD is an unsigned int, so we need to
+ // explicitly compare with -1.
previous_suspend_count = ::ResumeThread(thread_handle);
- } while (previous_suspend_count > 0);
+
+ if (previous_suspend_count == (DWORD)-1)
+ return Status(::GetLastError(), eErrorTypeWin32);
+
+ } while (previous_suspend_count > 1);
}
- return true;
+
+ return Status();
}
diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.h b/source/Plugins/Process/Windows/Common/TargetThreadWindows.h
index 8b4e3dfdda4a..952c0f55b57f 100644
--- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.h
+++ b/source/Plugins/Process/Windows/Common/TargetThreadWindows.h
@@ -37,15 +37,14 @@ public:
bool CalculateStopInfo() override;
Unwind *GetUnwinder() override;
- bool DoResume();
+ Status DoResume();
HostThread GetHostThread() const { return m_host_thread; }
private:
- lldb::RegisterContextSP CreateRegisterContextForFrameIndex(uint32_t idx);
-
+ lldb::RegisterContextSP m_thread_reg_ctx_sp;
HostThread m_host_thread;
};
-}
+} // namespace lldb_private
#endif
diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp
index e64bade5ff90..4aa6c785f83c 100644
--- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp
+++ b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp
@@ -14,9 +14,9 @@
#include "lldb/lldb-private-types.h"
#include "RegisterContextWindows_x64.h"
-#include "RegisterContext_x86.h"
+#include "Plugins/Process/Utility/RegisterContext_x86.h"
#include "TargetThreadWindows.h"
-#include "lldb-x86-register-enums.h"
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
#include "llvm/ADT/STLExtras.h"
@@ -29,14 +29,11 @@ using namespace lldb_private;
namespace {
// This enum defines the layout of the global RegisterInfo array. This is
-// necessary because
-// lldb register sets are defined in terms of indices into the register array.
-// As such, the
-// order of RegisterInfos defined in global registers array must match the order
-// defined here.
-// When defining the register set layouts, these values can appear in an
-// arbitrary order, and that
-// determines the order that register values are displayed in a dump.
+// necessary because lldb register sets are defined in terms of indices into
+// the register array. As such, the order of RegisterInfos defined in global
+// registers array must match the order defined here. When defining the
+// register set layouts, these values can appear in an arbitrary order, and
+// that determines the order that register values are displayed in a dump.
enum RegisterIndex {
eRegisterIndexRax,
eRegisterIndexRbx,
@@ -44,6 +41,8 @@ enum RegisterIndex {
eRegisterIndexRdx,
eRegisterIndexRdi,
eRegisterIndexRsi,
+ eRegisterIndexRbp,
+ eRegisterIndexRsp,
eRegisterIndexR8,
eRegisterIndexR9,
eRegisterIndexR10,
@@ -52,8 +51,6 @@ enum RegisterIndex {
eRegisterIndexR13,
eRegisterIndexR14,
eRegisterIndexR15,
- eRegisterIndexRbp,
- eRegisterIndexRsp,
eRegisterIndexRip,
eRegisterIndexRflags
};
@@ -96,6 +93,16 @@ RegisterInfo g_register_infos[] = {
LLDB_INVALID_REGNUM, lldb_rsi_x86_64},
nullptr,
nullptr},
+ {DEFINE_GPR(rbp, "fp"),
+ {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP,
+ LLDB_INVALID_REGNUM, lldb_rbp_x86_64},
+ nullptr,
+ nullptr},
+ {DEFINE_GPR(rsp, "sp"),
+ {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP,
+ LLDB_INVALID_REGNUM, lldb_rsp_x86_64},
+ nullptr,
+ nullptr},
{DEFINE_GPR(r8, nullptr),
{dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r8_x86_64},
@@ -136,16 +143,6 @@ RegisterInfo g_register_infos[] = {
LLDB_INVALID_REGNUM, lldb_r15_x86_64},
nullptr,
nullptr},
- {DEFINE_GPR(rbp, "fp"),
- {dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP,
- LLDB_INVALID_REGNUM, lldb_rbp_x86_64},
- nullptr,
- nullptr},
- {DEFINE_GPR(rsp, "sp"),
- {dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP,
- LLDB_INVALID_REGNUM, lldb_rsp_x86_64},
- nullptr,
- nullptr},
{DEFINE_GPR(rip, "pc"),
{dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC,
LLDB_INVALID_REGNUM, lldb_rip_x86_64},
@@ -165,10 +162,10 @@ static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
uint32_t g_gpr_reg_indices[] = {
eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx,
eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi,
- eRegisterIndexR8, eRegisterIndexR9, eRegisterIndexR10,
- eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13,
- eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp,
- eRegisterIndexRsp, eRegisterIndexRip, eRegisterIndexRflags};
+ eRegisterIndexRbp, eRegisterIndexRsp, eRegisterIndexR8,
+ eRegisterIndexR9, eRegisterIndexR10, eRegisterIndexR11,
+ eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14,
+ eRegisterIndexR15, eRegisterIndexRip, eRegisterIndexRflags};
RegisterSet g_register_sets[] = {
{"General Purpose Registers", "gpr",
@@ -209,6 +206,9 @@ bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
if (!CacheAllRegisterValues())
return false;
+ if (reg_info == nullptr)
+ return false;
+
switch (reg_info->kinds[eRegisterKindLLDB]) {
case lldb_rax_x86_64:
reg_value.SetUInt64(m_context.Rax);
@@ -270,11 +270,10 @@ bool RegisterContextWindows_x64::ReadRegister(const RegisterInfo *reg_info,
bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) {
- // Since we cannot only write a single register value to the inferior, we need
- // to make sure
- // our cached copy of the register values are fresh. Otherwise when writing
- // EAX, for example,
- // we may also overwrite some other register with a stale value.
+ // Since we cannot only write a single register value to the inferior, we
+ // need to make sure our cached copy of the register values are fresh.
+ // Otherwise when writing EAX, for example, we may also overwrite some other
+ // register with a stale value.
if (!CacheAllRegisterValues())
return false;
diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp
index f56836de4a67..fd486f3d0829 100644
--- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp
+++ b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp
@@ -15,9 +15,9 @@
#include "ProcessWindowsLog.h"
#include "RegisterContextWindows_x86.h"
-#include "RegisterContext_x86.h"
+#include "Plugins/Process/Utility/RegisterContext_x86.h"
#include "TargetThreadWindows.h"
-#include "lldb-x86-register-enums.h"
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
#include "llvm/ADT/STLExtras.h"
@@ -30,14 +30,11 @@ using namespace lldb_private;
namespace {
// This enum defines the layout of the global RegisterInfo array. This is
-// necessary because
-// lldb register sets are defined in terms of indices into the register array.
-// As such, the
-// order of RegisterInfos defined in global registers array must match the order
-// defined here.
-// When defining the register set layouts, these values can appear in an
-// arbitrary order, and that
-// determines the order that register values are displayed in a dump.
+// necessary because lldb register sets are defined in terms of indices into
+// the register array. As such, the order of RegisterInfos defined in global
+// registers array must match the order defined here. When defining the
+// register set layouts, these values can appear in an arbitrary order, and
+// that determines the order that register values are displayed in a dump.
enum RegisterIndex {
eRegisterIndexEax,
eRegisterIndexEbx,
@@ -179,6 +176,9 @@ bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
if (!CacheAllRegisterValues())
return false;
+ if (reg_info == nullptr)
+ return false;
+
uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
switch (reg) {
case lldb_eax_i386:
@@ -212,11 +212,10 @@ bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) {
- // Since we cannot only write a single register value to the inferior, we need
- // to make sure
- // our cached copy of the register values are fresh. Otherwise when writing
- // EAX, for example,
- // we may also overwrite some other register with a stale value.
+ // Since we cannot only write a single register value to the inferior, we
+ // need to make sure our cached copy of the register values are fresh.
+ // Otherwise when writing EAX, for example, we may also overwrite some other
+ // register with a stale value.
if (!CacheAllRegisterValues())
return false;
diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt
index 3082c73f6dda..9b6739824c06 100644
--- a/source/Plugins/Process/elf-core/CMakeLists.txt
+++ b/source/Plugins/Process/elf-core/CMakeLists.txt
@@ -1,5 +1,3 @@
-include_directories(../Utility)
-
add_lldb_library(lldbPluginProcessElfCore PLUGIN
ProcessElfCore.cpp
ThreadElfCore.cpp
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 7d6a0c9ad2df..7bb7b72eaac1 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -56,9 +56,9 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,
const FileSpec *crash_file) {
lldb::ProcessSP process_sp;
if (crash_file) {
- // Read enough data for a ELF32 header or ELF64 header
- // Note: Here we care about e_type field only, so it is safe
- // to ignore possible presence of the header extension.
+ // Read enough data for a ELF32 header or ELF64 header Note: Here we care
+ // about e_type field only, so it is safe to ignore possible presence of
+ // the header extension.
const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);
auto data_sp = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(),
@@ -107,10 +107,10 @@ ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,
//----------------------------------------------------------------------
ProcessElfCore::~ProcessElfCore() {
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
}
@@ -206,8 +206,8 @@ Status ProcessElfCore::DoLoadCore() {
m_core_range_infos.Sort();
}
- // Even if the architecture is set in the target, we need to override
- // it to match the core file which is always single arch.
+ // Even if the architecture is set in the target, we need to override it to
+ // match the core file which is always single arch.
ArchSpec arch(m_core_module_sp->GetArchitecture());
ArchSpec target_arch = GetTarget().GetArchitecture();
@@ -241,8 +241,7 @@ Status ProcessElfCore::DoLoadCore() {
}
// Core files are useless without the main executable. See if we can locate
- // the main
- // executable using data we found in the core file notes.
+ // the main executable using data we found in the core file notes.
lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
if (!exe_module_sp) {
// The first entry in the NT_FILE might be our executable
@@ -250,7 +249,8 @@ Status ProcessElfCore::DoLoadCore() {
ModuleSpec exe_module_spec;
exe_module_spec.GetArchitecture() = arch;
exe_module_spec.GetFileSpec().SetFile(
- m_nt_file_entries[0].path.GetCString(), false);
+ m_nt_file_entries[0].path.GetCString(), false,
+ FileSpec::Style::native);
if (exe_module_spec.GetFileSpec()) {
exe_module_sp = GetTarget().GetSharedModule(exe_module_spec);
if (exe_module_sp)
@@ -297,8 +297,8 @@ bool ProcessElfCore::IsAlive() { return true; }
//------------------------------------------------------------------
size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) {
- // Don't allow the caching that lldb_private::Process::ReadMemory does
- // since in core files we have it all cached our our core file anyway.
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // in core files we have it all cached our our core file anyway.
return DoReadMemory(addr, buf, size, error);
}
@@ -368,17 +368,18 @@ size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
lldb::addr_t bytes_left =
0; // Number of bytes available in the core file from the given address
- // Don't proceed if core file doesn't contain the actual data for this address range.
+ // Don't proceed if core file doesn't contain the actual data for this
+ // address range.
if (file_start == file_end)
return 0;
- // Figure out how many on-disk bytes remain in this segment
- // starting at the given offset
+ // Figure out how many on-disk bytes remain in this segment starting at the
+ // given offset
if (file_end > file_start + offset)
bytes_left = file_end - (file_start + offset);
- // Figure out how many bytes we need to zero-fill if we are
- // reading more bytes than available in the on-disk segment
+ // Figure out how many bytes we need to zero-fill if we are reading more
+ // bytes than available in the on-disk segment
if (bytes_to_read > bytes_left) {
zero_fill_size = bytes_to_read - bytes_left;
bytes_to_read = bytes_left;
@@ -551,8 +552,8 @@ llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
ThreadData thread_data;
for (const auto &note : notes) {
- // NetBSD per-thread information is stored in notes named
- // "NetBSD-CORE@nnn" so match on the initial part of the string.
+ // NetBSD per-thread information is stored in notes named "NetBSD-CORE@nnn"
+ // so match on the initial part of the string.
if (!llvm::StringRef(note.info.n_name).startswith("NetBSD-CORE"))
continue;
@@ -585,8 +586,8 @@ llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {
ThreadData thread_data;
for (const auto &note : notes) {
- // OpenBSD per-thread information is stored in notes named
- // "OpenBSD@nnn" so match on the initial part of the string.
+ // OpenBSD per-thread information is stored in notes named "OpenBSD@nnn" so
+ // match on the initial part of the string.
if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD"))
continue;
@@ -665,7 +666,7 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
Status status = prpsinfo.Parse(note.data, arch);
if (status.Fail())
return status.ToError();
- thread_data.name = prpsinfo.pr_fname;
+ thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname)));
SetID(prpsinfo.pr_pid);
break;
}
@@ -749,9 +750,9 @@ ArchSpec ProcessElfCore::GetArchitecture() {
ArchSpec target_arch = GetTarget().GetArchitecture();
arch.MergeFrom(target_arch);
- // On MIPS there is no way to differentiate betwenn 32bit and 64bit core files
- // and this information can't be merged in from the target arch so we fail
- // back to unconditionally returning the target arch in this config.
+ // On MIPS there is no way to differentiate betwenn 32bit and 64bit core
+ // files and this information can't be merged in from the target arch so we
+ // fail back to unconditionally returning the target arch in this config.
if (target_arch.IsMIPS()) {
return target_arch;
}
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index e252b5a35e9c..532a1f5c0831 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -56,7 +56,7 @@ bool RegisterContextCorePOSIX_mips64::ReadRegister(const RegisterInfo *reg_info,
if (IsGPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
if (reg_info->byte_size == 4 && !(arch.GetMachine() == llvm::Triple::mips64el))
// In case of 32bit core file, the register data are placed at 4 byte
- // offset.
+ // offset.
offset = offset / 2;
v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
value = v;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index a5c7ffda1da5..a1f26d52444b 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -60,8 +60,8 @@ bool RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info,
const uint8_t *src;
size_t offset;
const size_t fxsave_offset = reg_info->byte_offset - GetFXSAVEOffset();
- // make the offset relative to the beginning of the FXSAVE structure
- // because this is the data that we have (not the entire UserArea)
+ // make the offset relative to the beginning of the FXSAVE structure because
+ // this is the data that we have (not the entire UserArea)
if (m_gpregset && reg_info->byte_offset < GetGPRSize()) {
src = m_gpregset.get();
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 10c1ed288b2c..d9b90c8e902e 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -55,16 +55,9 @@ void ThreadElfCore::RefreshStateAfterStop() {
GetRegisterContext()->InvalidateIfNeeded(false);
}
-void ThreadElfCore::ClearStackFrames() {
- Unwind *unwinder = GetUnwinder();
- if (unwinder)
- unwinder->Clear();
- Thread::ClearStackFrames();
-}
-
RegisterContextSP ThreadElfCore::GetRegisterContext() {
- if (m_reg_context_sp.get() == NULL) {
- m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ if (!m_reg_context_sp) {
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
}
return m_reg_context_sp;
}
@@ -84,7 +77,7 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
ArchSpec arch = process->GetArchitecture();
- RegisterInfoInterface *reg_interface = NULL;
+ RegisterInfoInterface *reg_interface = nullptr;
switch (arch.GetTriple().getOS()) {
case llvm::Triple::FreeBSD: {
@@ -234,8 +227,10 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
}
reg_ctx_sp = m_thread_reg_ctx_sp;
- } else if (m_unwinder_ap.get()) {
- reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame(frame);
+ } else {
+ Unwind *unwinder = GetUnwinder();
+ if (unwinder != nullptr)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
}
@@ -292,8 +287,8 @@ Status ELFLinuxPrStatus::Parse(const DataExtractor &data,
return error;
}
- // Read field by field to correctly account for endianess
- // of both the core dump and the platform running lldb.
+ // Read field by field to correctly account for endianess of both the core
+ // dump and the platform running lldb.
offset_t offset = 0;
si_signo = data.GetU32(&offset);
si_code = data.GetU32(&offset);
@@ -340,7 +335,7 @@ size_t ELFLinuxPrPsInfo::GetSize(const lldb_private::ArchSpec &arch) {
return sizeof(ELFLinuxPrPsInfo);
return mips_linux_pr_psinfo_size_o32_n32;
}
-
+
switch (arch.GetCore()) {
case lldb_private::ArchSpec::eCore_s390x_generic:
case lldb_private::ArchSpec::eCore_x86_64_x86_64:
@@ -382,9 +377,9 @@ Status ELFLinuxPrPsInfo::Parse(const DataExtractor &data,
pr_uid = data.GetU32(&offset);
pr_gid = data.GetU32(&offset);
} else {
- // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
- pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
- pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
+ // 16 bit on 32 bit platforms, 32 bit on 64 bit platforms
+ pr_uid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
+ pr_gid = data.GetMaxU64(&offset, data.GetAddressByteSize() >> 1);
}
pr_pid = data.GetU32(&offset);
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h
index 335f698dbb24..167fd6edc4ce 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -146,8 +146,6 @@ public:
lldb::RegisterContextSP
CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
- void ClearStackFrames() override;
-
static bool ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
const char *GetName() override {
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index 4d4a4f8c5c7a..4e20b56fb111 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -109,16 +109,14 @@ StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
const bool should_stop = ShouldStop(signals, response);
response.SetFilePos(0);
- // The packet we should resume with. In the future
- // we should check our thread list and "do the right thing"
- // for new threads that show up while we stop and run async
- // packets. Setting the packet to 'c' to continue all threads
- // is the right thing to do 99.99% of the time because if a
- // thread was single stepping, and we sent an interrupt, we
- // will notice above that we didn't stop due to an interrupt
- // but stopped due to stepping and we would _not_ continue.
- // This packet may get modified by the async actions (e.g. to send a
- // signal).
+ // The packet we should resume with. In the future we should check our
+ // thread list and "do the right thing" for new threads that show up
+ // while we stop and run async packets. Setting the packet to 'c' to
+ // continue all threads is the right thing to do 99.99% of the time
+ // because if a thread was single stepping, and we sent an interrupt, we
+ // will notice above that we didn't stop due to an interrupt but stopped
+ // due to stepping and we would _not_ continue. This packet may get
+ // modified by the async actions (e.g. to send a signal).
m_continue_packet = 'c';
cont_lock.unlock();
@@ -177,6 +175,30 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse(
}
GDBRemoteCommunication::PacketResult
+GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ bool send_async,
+ llvm::function_ref<void(llvm::StringRef)> output_callback) {
+ Lock lock(*this, send_async);
+ if (!lock) {
+ if (Log *log =
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
+ log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending "
+ "packet '%.*s' (send_async=%d)",
+ __FUNCTION__, int(payload.size()), payload.data(),
+ send_async);
+ return PacketResult::ErrorSendFailed;
+ }
+
+ PacketResult packet_result = SendPacketNoLock(payload);
+ if (packet_result != PacketResult::Success)
+ return packet_result;
+
+ return ReadPacketWithOutputSupport(response, GetPacketTimeout(), true,
+ output_callback);
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
llvm::StringRef payload, StringExtractorGDBRemote &response) {
PacketResult packet_result = SendPacketNoLock(payload);
@@ -239,19 +261,16 @@ bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
if (m_async_count == 0)
return true; // We were not interrupted. The process stopped on its own.
- // Older debugserver stubs (before April 2016) can return two
- // stop-reply packets in response to a ^C packet.
- // Additionally, all debugservers still return two stop replies if
- // the inferior stops due to some other reason before the remote
- // stub manages to interrupt it. We need to wait for this
- // additional packet to make sure the packet sequence does not get
- // skewed.
+ // Older debugserver stubs (before April 2016) can return two stop-reply
+ // packets in response to a ^C packet. Additionally, all debugservers still
+ // return two stop replies if the inferior stops due to some other reason
+ // before the remote stub manages to interrupt it. We need to wait for this
+ // additional packet to make sure the packet sequence does not get skewed.
StringExtractorGDBRemote extra_stop_reply_packet;
ReadPacket(extra_stop_reply_packet, milliseconds(100), false);
- // Interrupting is typically done using SIGSTOP or SIGINT, so if
- // the process stops with some other signal, we definitely want to
- // stop.
+ // Interrupting is typically done using SIGSTOP or SIGINT, so if the process
+ // stops with some other signal, we definitely want to stop.
const uint8_t signo = response.GetHexU8(UINT8_MAX);
if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
signo != signals.GetSignalNumberFromName("SIGINT"))
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
index 2646405c9b91..3d84ce0ebe18 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -48,6 +48,11 @@ public:
StringExtractorGDBRemote &response,
bool send_async);
+ PacketResult SendPacketAndReceiveResponseWithOutputSupport(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ bool send_async,
+ llvm::function_ref<void(llvm::StringRef)> output_callback);
+
bool SendvContPacket(llvm::StringRef payload,
StringExtractorGDBRemote &response);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 949cf19db658..c335b6002861 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -150,9 +150,8 @@ GDBRemoteCommunication::~GDBRemoteCommunication() {
Disconnect();
}
- // Stop the communications read thread which is used to parse all
- // incoming packets. This function will block until the read
- // thread returns.
+ // Stop the communications read thread which is used to parse all incoming
+ // packets. This function will block until the read thread returns.
if (m_read_thread_enabled)
StopReadThread();
}
@@ -217,12 +216,10 @@ GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {
}
}
- // If logging was just enabled and we have history, then dump out what
- // we have to the log so we get the historical context. The Dump() call
- // that
+ // If logging was just enabled and we have history, then dump out what we
+ // have to the log so we get the historical context. The Dump() call that
// logs all of the packet will set a boolean so that we don't dump this
- // more
- // than once
+ // more than once
if (!m_history.DidDumpToLog())
m_history.Dump(log);
@@ -275,6 +272,23 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() {
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunication::ReadPacketWithOutputSupport(
+ StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
+ bool sync_on_timeout,
+ llvm::function_ref<void(llvm::StringRef)> output_callback) {
+ auto result = ReadPacket(response, timeout, sync_on_timeout);
+ while (result == PacketResult::Success && response.IsNormalResponse() &&
+ response.PeekChar() == 'O') {
+ response.GetChar();
+ std::string output;
+ if (response.GetHexByteString(output))
+ output_callback(output);
+ result = ReadPacket(response, timeout, sync_on_timeout);
+ }
+ return result;
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout,
bool sync_on_timeout) {
@@ -286,8 +300,8 @@ GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
// This function is called when a packet is requested.
// A whole packet is popped from the packet queue and returned to the caller.
-// Packets are placed into this queue from the communication read thread.
-// See GDBRemoteCommunication::AppendBytesToCache.
+// Packets are placed into this queue from the communication read thread. See
+// GDBRemoteCommunication::AppendBytesToCache.
GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::PopPacketFromQueue(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout) {
@@ -407,11 +421,9 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
break;
} else if (successful_responses == 1) {
// We got something else back as the first successful
- // response, it probably is
- // the response to the packet we actually wanted, so copy it
- // over if this
- // is the first success and continue to try to get the qEcho
- // response
+ // response, it probably is the response to the packet we
+ // actually wanted, so copy it over if this is the first
+ // success and continue to try to get the qEcho response
packet = echo_response;
got_actual_response = true;
}
@@ -424,14 +436,13 @@ GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
}
// We weren't able to sync back up with the server, we must abort
- // otherwise
- // all responses might not be from the right packets...
+ // otherwise all responses might not be from the right packets...
if (sync_success) {
// We timed out, but were able to recover
if (got_actual_response) {
// We initially timed out, but we did get a response that came in
- // before the successful
- // reply to our qEcho packet, so lets say everything is fine...
+ // before the successful reply to our qEcho packet, so lets say
+ // everything is fine...
return PacketResult::Success;
}
} else {
@@ -473,10 +484,9 @@ bool GDBRemoteCommunication::DecompressPacket() {
size_t pkt_size = m_bytes.size();
- // Smallest possible compressed packet is $N#00 - an uncompressed empty reply,
- // most commonly indicating
- // an unsupported packet. Anything less than 5 characters, it's definitely
- // not a compressed packet.
+ // Smallest possible compressed packet is $N#00 - an uncompressed empty
+ // reply, most commonly indicating an unsupported packet. Anything less than
+ // 5 characters, it's definitely not a compressed packet.
if (pkt_size < 5)
return true;
@@ -505,17 +515,15 @@ bool GDBRemoteCommunication::DecompressPacket() {
1; // The first character of the two hex checksum characters
// Normally size_of_first_packet == m_bytes.size() but m_bytes may contain
- // multiple packets.
- // size_of_first_packet is the size of the initial packet which we'll replace
- // with the decompressed
- // version of, leaving the rest of m_bytes unmodified.
+ // multiple packets. size_of_first_packet is the size of the initial packet
+ // which we'll replace with the decompressed version of, leaving the rest of
+ // m_bytes unmodified.
size_t size_of_first_packet = hash_mark_idx + 3;
// Compressed packets ("$C") start with a base10 number which is the size of
- // the uncompressed payload,
- // then a : and then the compressed data. e.g. $C1024:<binary>#00
- // Update content_start and content_length to only include the <binary> part
- // of the packet.
+ // the uncompressed payload, then a : and then the compressed data. e.g.
+ // $C1024:<binary>#00 Update content_start and content_length to only include
+ // the <binary> part of the packet.
uint64_t decompressed_bufsize = ULONG_MAX;
if (m_bytes[1] == 'C') {
@@ -564,15 +572,14 @@ bool GDBRemoteCommunication::DecompressPacket() {
}
if (m_bytes[1] == 'N') {
- // This packet was not compressed -- delete the 'N' character at the
- // start and the packet may be processed as-is.
+ // This packet was not compressed -- delete the 'N' character at the start
+ // and the packet may be processed as-is.
m_bytes.erase(1, 1);
return true;
}
- // Reverse the gdb-remote binary escaping that was done to the compressed text
- // to
- // guard characters like '$', '#', '}', etc.
+ // Reverse the gdb-remote binary escaping that was done to the compressed
+ // text to guard characters like '$', '#', '}', etc.
std::vector<uint8_t> unescaped_content;
unescaped_content.reserve(content_length);
size_t i = content_start;
@@ -613,12 +620,10 @@ bool GDBRemoteCommunication::DecompressPacket() {
else if (m_compression_type == CompressionType::LZMA)
compression_type = COMPRESSION_LZMA;
- // If we have the expected size of the decompressed payload, we can allocate
- // the right-sized buffer and do it. If we don't have that information,
- // we'll
- // need to try decoding into a big buffer and if the buffer wasn't big
- // enough,
- // increase it and try again.
+ // If we have the expected size of the decompressed payload, we can
+ // allocate the right-sized buffer and do it. If we don't have that
+ // information, we'll need to try decoding into a big buffer and if the
+ // buffer wasn't big enough, increase it and try again.
if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) {
decompressed_bytes = compression_decode_buffer(
@@ -706,9 +711,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Parse up the packets into gdb remote packets
if (!m_bytes.empty()) {
- // end_idx must be one past the last valid packet byte. Start
- // it off with an invalid value that is the same as the current
- // index.
+ // end_idx must be one past the last valid packet byte. Start it off with
+ // an invalid value that is the same as the current index.
size_t content_start = 0;
size_t content_length = 0;
size_t total_length = 0;
@@ -743,7 +747,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
checksum_idx = hash_pos + 1;
// Skip the dollar sign
content_start = 1;
- // Don't include the # in the content or the $ in the content length
+ // Don't include the # in the content or the $ in the content
+ // length
content_length = hash_pos - 1;
total_length =
@@ -757,11 +762,10 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
break;
default: {
- // We have an unexpected byte and we need to flush all bad
- // data that is in m_bytes, so we need to find the first
- // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
- // or '$' character (start of packet header) or of course,
- // the end of the data in m_bytes...
+ // We have an unexpected byte and we need to flush all bad data that is
+ // in m_bytes, so we need to find the first byte that is a '+' (ACK), '-'
+ // (NACK), \x03 (CTRL+C interrupt), or '$' character (start of packet
+ // header) or of course, the end of the data in m_bytes...
const size_t bytes_len = m_bytes.size();
bool done = false;
uint32_t idx;
@@ -802,16 +806,14 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
if (log) {
// If logging was just enabled and we have history, then dump out what
// we have to the log so we get the historical context. The Dump() call
- // that
- // logs all of the packet will set a boolean so that we don't dump this
- // more
- // than once
+ // that logs all of the packet will set a boolean so that we don't dump
+ // this more than once
if (!m_history.DidDumpToLog())
m_history.Dump(log);
bool binary = false;
- // Only detect binary for packets that start with a '$' and have a '#CC'
- // checksum
+ // Only detect binary for packets that start with a '$' and have a
+ // '#CC' checksum
if (m_bytes[0] == '$' && total_length > 4) {
for (size_t i = 0; !binary && i < total_length; ++i) {
unsigned char c = m_bytes[i];
@@ -834,8 +836,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Remove binary escaped bytes when displaying the packet...
const char ch = m_bytes[i];
if (ch == 0x7d) {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
+ // 0x7d is the escape character. The next character is to be
+ // XOR'd with 0x20.
const char escapee = m_bytes[++i] ^ 0x20;
strm.Printf("%2.2x", escapee);
} else {
@@ -863,26 +865,25 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Clear packet_str in case there is some existing data in it.
packet_str.clear();
- // Copy the packet from m_bytes to packet_str expanding the
- // run-length encoding in the process.
- // Reserve enough byte for the most common case (no RLE used)
+ // Copy the packet from m_bytes to packet_str expanding the run-length
+ // encoding in the process. Reserve enough byte for the most common case
+ // (no RLE used)
packet_str.reserve(m_bytes.length());
for (std::string::const_iterator c = m_bytes.begin() + content_start;
c != m_bytes.begin() + content_end; ++c) {
if (*c == '*') {
- // '*' indicates RLE. Next character will give us the
- // repeat count and previous character is what is to be
- // repeated.
+ // '*' indicates RLE. Next character will give us the repeat count
+ // and previous character is what is to be repeated.
char char_to_repeat = packet_str.back();
// Number of time the previous character is repeated
int repeat_count = *++c + 3 - ' ';
- // We have the char_to_repeat and repeat_count. Now push
- // it in the packet.
+ // We have the char_to_repeat and repeat_count. Now push it in the
+ // packet.
for (int i = 0; i < repeat_count; ++i)
packet_str.push_back(char_to_repeat);
} else if (*c == 0x7d) {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
+ // 0x7d is the escape character. The next character is to be XOR'd
+ // with 0x20.
char escapee = *++c ^ 0x20;
packet_str.push_back(escapee);
} else {
@@ -897,7 +898,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
if (GetSendAcks()) {
const char *packet_checksum_cstr = &m_bytes[checksum_idx];
char packet_checksum = strtol(packet_checksum_cstr, NULL, 16);
- char actual_checksum = CalculcateChecksum(packet_str);
+ char actual_checksum = CalculcateChecksum(
+ llvm::StringRef(m_bytes).slice(content_start, content_end));
success = packet_checksum == actual_checksum;
if (!success) {
if (log)
@@ -991,11 +993,12 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
char debugserver_path[PATH_MAX];
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
- // Always check to see if we have an environment override for the path
- // to the debugserver to use and use it if we do.
+ // Always check to see if we have an environment override for the path to the
+ // debugserver to use and use it if we do.
const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
if (env_debugserver_path) {
- debugserver_file_spec.SetFile(env_debugserver_path, false);
+ debugserver_file_spec.SetFile(env_debugserver_path, false,
+ FileSpec::Style::native);
if (log)
log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set "
"from environment variable: %s",
@@ -1004,10 +1007,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
debugserver_file_spec = g_debugserver_file_spec;
bool debugserver_exists = debugserver_file_spec.Exists();
if (!debugserver_exists) {
- // The debugserver binary is in the LLDB.framework/Resources
- // directory.
- if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir,
- debugserver_file_spec)) {
+ // The debugserver binary is in the LLDB.framework/Resources directory.
+ debugserver_file_spec = HostInfo::GetSupportExeDir();
+ if (debugserver_file_spec) {
debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME);
debugserver_exists = debugserver_file_spec.Exists();
if (debugserver_exists) {
@@ -1031,8 +1033,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
__FUNCTION__, debugserver_file_spec.GetPath().c_str());
}
// Don't cache the platform specific GDB server binary as it could
- // change
- // from platform to platform
+ // change from platform to platform
g_debugserver_file_spec.Clear();
}
}
@@ -1080,14 +1081,14 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
// once data is written to the pipe, debug server is up and running.
Pipe socket_pipe;
- // port is null when debug server should listen on domain socket -
- // we're not interested in port value but rather waiting for debug server
- // to become available.
+ // port is null when debug server should listen on domain socket - we're
+ // not interested in port value but rather waiting for debug server to
+ // become available.
if (pass_comm_fd == -1) {
if (url) {
-// Create a temporary file to get the stdout/stderr and redirect the
-// output of the command into this file. We will later read this file
-// if all goes well and fill the data into "command_output_ptr"
+// Create a temporary file to get the stdout/stderr and redirect the output of
+// the command into this file. We will later read this file if all goes well
+// and fill the data into "command_output_ptr"
#if defined(__APPLE__)
// Binding to port zero, we need to figure out what port it ends up
// using using a named pipe...
@@ -1120,8 +1121,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
#endif
} else {
// No host and port given, so lets listen on our end and make the
- // debugserver
- // connect to us..
+ // debugserver connect to us..
error = StartListenThread("127.0.0.1", 0);
if (error.Fail()) {
if (log)
@@ -1134,7 +1134,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
ConnectionFileDescriptor *connection =
(ConnectionFileDescriptor *)GetConnection();
// Wait for 10 seconds to resolve the bound port
- uint16_t port_ = connection->GetListeningPort(10);
+ uint16_t port_ = connection->GetListeningPort(std::chrono::seconds(10));
if (port_ > 0) {
char port_cstr[32];
snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", port_);
@@ -1206,11 +1206,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
}
// Copy the current environment to the gdbserver/debugserver instance
- StringList env;
- if (Host::GetEnvironment(env)) {
- for (size_t i = 0; i < env.GetSize(); ++i)
- launch_info.GetEnvironmentEntries().AppendArgument(env[i]);
- }
+ launch_info.GetEnvironment() = Host::GetEnvironment();
// Close STDIN, STDOUT and STDERR.
launch_info.AppendCloseFileAction(STDIN_FILENO);
@@ -1327,14 +1323,11 @@ GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() {
}
// This function is called via the Communications class read thread when bytes
-// become available
-// for this connection. This function will consume all incoming bytes and try to
-// parse whole
-// packets as they become available. Full packets are placed in a queue, so that
-// all packet
-// requests can simply pop from this queue. Async notification packets will be
-// dispatched
-// immediately to the ProcessGDBRemote Async thread via an event.
+// become available for this connection. This function will consume all
+// incoming bytes and try to parse whole packets as they become available. Full
+// packets are placed in a queue, so that all packet requests can simply pop
+// from this queue. Async notification packets will be dispatched immediately
+// to the ProcessGDBRemote Async thread via an event.
void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
size_t len, bool broadcast,
lldb::ConnectionStatus status) {
@@ -1343,8 +1336,8 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
while (true) {
PacketType type = CheckForPacket(bytes, len, packet);
- // scrub the data so we do not pass it back to CheckForPacket
- // on future passes of the loop
+ // scrub the data so we do not pass it back to CheckForPacket on future
+ // passes of the loop
bytes = nullptr;
len = 0;
@@ -1368,8 +1361,8 @@ void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
// put this packet into an event
const char *pdata = packet.GetStringRef().c_str();
- // as the communication class, we are a broadcaster and the
- // async thread is tuned to listen to us
+ // as the communication class, we are a broadcaster and the async thread
+ // is tuned to listen to us
BroadcastEvent(eBroadcastBitGdbReadThreadGotNotify,
new EventDataBytes(pdata));
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index ecc9386e49c7..67796e4c61ef 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -24,10 +24,10 @@
#include "lldb/Core/Listener.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Predicate.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/Args.h"
#include "lldb/lldb-public.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
namespace lldb_private {
namespace process_gdb_remote {
@@ -232,6 +232,11 @@ protected:
PacketResult ReadPacket(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout, bool sync_on_timeout);
+ PacketResult ReadPacketWithOutputSupport(
+ StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
+ bool sync_on_timeout,
+ llvm::function_ref<void(llvm::StringRef)> output_callback);
+
// Pop a packet from the queue in a thread safe manner
PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 867f57c475ce..c8b59d5d236b 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -21,11 +21,12 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Host/XML.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -35,8 +36,8 @@
// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Host/Config.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "llvm/ADT/StringSwitch.h"
@@ -81,6 +82,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_qXfer_libraries_read(eLazyBoolCalculate),
m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate),
m_supports_qXfer_features_read(eLazyBoolCalculate),
+ m_supports_qXfer_memory_map_read(eLazyBoolCalculate),
m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
@@ -98,12 +100,12 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID),
m_curr_tid_run(LLDB_INVALID_THREAD_ID),
m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(),
- m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX),
- m_os_version_update(UINT32_MAX), m_os_build(), m_os_kernel(),
- m_hostname(), m_gdb_server_name(), m_gdb_server_version(UINT32_MAX),
- m_default_packet_timeout(0), m_max_packet_size(0),
- m_qSupported_response(), m_supported_async_json_packets_is_valid(false),
- m_supported_async_json_packets_sp() {}
+ m_os_build(), m_os_kernel(), m_hostname(), m_gdb_server_name(),
+ m_gdb_server_version(UINT32_MAX), m_default_packet_timeout(0),
+ m_max_packet_size(0), m_qSupported_response(),
+ m_supported_async_json_packets_is_valid(false),
+ m_supported_async_json_packets_sp(), m_qXfer_memory_map(),
+ m_qXfer_memory_map_loaded(false) {}
//----------------------------------------------------------------------
// Destructor
@@ -116,8 +118,8 @@ GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
ResetDiscoverableSettings(false);
- // Start the read thread after we send the handshake ack since if we
- // fail to send the handshake ack, there is no reason to continue...
+ // Start the read thread after we send the handshake ack since if we fail to
+ // send the handshake ack, there is no reason to continue...
if (SendAck()) {
// Wait for any responses that might have been queued up in the remote
// GDB server and flush them all
@@ -127,9 +129,9 @@ bool GDBRemoteCommunicationClient::HandshakeWithServer(Status *error_ptr) {
packet_result = ReadPacket(response, milliseconds(10), false);
// The return value from QueryNoAckModeSupported() is true if the packet
- // was sent and _any_ response (including UNIMPLEMENTED) was received),
- // or false if no response was received. This quickly tells us if we have
- // a live connection to a remote GDB server...
+ // was sent and _any_ response (including UNIMPLEMENTED) was received), or
+ // false if no response was received. This quickly tells us if we have a
+ // live connection to a remote GDB server...
if (QueryNoAckModeSupported()) {
return true;
} else {
@@ -192,6 +194,13 @@ bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
return m_supports_qXfer_features_read == eLazyBoolYes;
}
+bool GDBRemoteCommunicationClient::GetQXferMemoryMapReadSupported() {
+ if (m_supports_qXfer_memory_map_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_memory_map_read == eLazyBoolYes;
+}
+
uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
if (m_max_packet_size == 0) {
GetRemoteQSupported();
@@ -205,9 +214,8 @@ bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
m_supports_not_sending_acks = eLazyBoolNo;
// This is the first real packet that we'll send in a debug session and it
- // may take a little
- // longer than normal to receive a reply. Wait at least 6 seconds for a
- // reply to this packet.
+ // may take a little longer than normal to receive a reply. Wait at least
+ // 6 seconds for a reply to this packet.
ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
@@ -296,6 +304,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_qXfer_libraries_read = eLazyBoolCalculate;
m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qXfer_features_read = eLazyBoolCalculate;
+ m_supports_qXfer_memory_map_read = eLazyBoolCalculate;
m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
m_supports_qfProcessInfo = true;
@@ -313,9 +322,7 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_qSymbol_requests_done = false;
m_supports_qModuleInfo = true;
m_host_arch.Clear();
- m_os_version_major = UINT32_MAX;
- m_os_version_minor = UINT32_MAX;
- m_os_version_update = UINT32_MAX;
+ m_os_version = llvm::VersionTuple();
m_os_build.clear();
m_os_kernel.clear();
m_hostname.clear();
@@ -329,8 +336,8 @@ void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
m_supports_jModulesInfo = true;
}
- // These flags should be reset when we first connect to a GDB server
- // and when our inferior process execs
+ // These flags should be reset when we first connect to a GDB server and when
+ // our inferior process execs
m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_process_arch.Clear();
}
@@ -342,6 +349,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
m_supports_qXfer_features_read = eLazyBoolNo;
+ m_supports_qXfer_memory_map_read = eLazyBoolNo;
m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
// not, we assume no limit
@@ -361,8 +369,7 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
const char *response_cstr = response.GetStringRef().c_str();
// Hang on to the qSupported packet, so that platforms can do custom
- // configuration of the transport before attaching/launching the
- // process.
+ // configuration of the transport before attaching/launching the process.
m_qSupported_response = response_cstr;
if (::strstr(response_cstr, "qXfer:auxv:read+"))
@@ -377,9 +384,12 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
m_supports_qXfer_libraries_read = eLazyBoolYes;
if (::strstr(response_cstr, "qXfer:features:read+"))
m_supports_qXfer_features_read = eLazyBoolYes;
+ if (::strstr(response_cstr, "qXfer:memory-map:read+"))
+ m_supports_qXfer_memory_map_read = eLazyBoolYes;
// Look for a list of compressions in the features list e.g.
- // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma
+ // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-
+ // deflate,lzma
const char *features_list = ::strstr(response_cstr, "qXfer:features:");
if (features_list) {
const char *compressions =
@@ -543,9 +553,8 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
}
-// Check if the target supports 'p' packet. It sends out a 'p'
-// packet and checks the response. A normal packet will tell us
-// that support is available.
+// Check if the target supports 'p' packet. It sends out a 'p' packet and
+// checks the response. A normal packet will tell us that support is available.
//
// Takes a valid thread ID because p needs to apply to a thread.
bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
@@ -600,8 +609,8 @@ bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
void GDBRemoteCommunicationClient::EnableErrorStringInPacket() {
if (m_supports_error_string_reply == eLazyBoolCalculate) {
StringExtractorGDBRemote response;
- // We try to enable error strings in remote packets
- // but if we fail, we just work in the older way.
+ // We try to enable error strings in remote packets but if we fail, we just
+ // work in the older way.
m_supports_error_string_reply = eLazyBoolNo;
if (SendPacketAndWaitForResponse("QEnableErrorStrings", response, false) ==
PacketResult::Success) {
@@ -715,12 +724,10 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
return m_curr_pid;
} else {
// If we don't get a response for qProcessInfo, check if $qC gives us a
- // result.
- // $qC only returns a real process id on older debugserver and lldb-platform
- // stubs.
- // The gdb remote protocol documents $qC as returning the thread id, which
- // newer
- // debugserver and lldb-gdbserver stubs return correctly.
+ // result. $qC only returns a real process id on older debugserver and
+ // lldb-platform stubs. The gdb remote protocol documents $qC as returning
+ // the thread id, which newer debugserver and lldb-gdbserver stubs return
+ // correctly.
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse("qC", response, false) ==
PacketResult::Success) {
@@ -775,8 +782,8 @@ bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
int GDBRemoteCommunicationClient::SendArgumentsPacket(
const ProcessLaunchInfo &launch_info) {
// Since we don't get the send argv0 separate from the executable path, we
- // need to
- // make sure to use the actual executable path found in the launch_info...
+ // need to make sure to use the actual executable path found in the
+ // launch_info...
std::vector<const char *> argv;
FileSpec exe_file = launch_info.GetExecutableFile();
std::string exe_path;
@@ -822,6 +829,15 @@ int GDBRemoteCommunicationClient::SendArgumentsPacket(
return -1;
}
+int GDBRemoteCommunicationClient::SendEnvironment(const Environment &env) {
+ for (const auto &KV : env) {
+ int r = SendEnvironmentPacket(Environment::compose(KV).c_str());
+ if (r != 0)
+ return r;
+ }
+ return 0;
+}
+
int GDBRemoteCommunicationClient::SendEnvironmentPacket(
char const *name_equal_value) {
if (name_equal_value && name_equal_value[0]) {
@@ -925,18 +941,9 @@ int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
return -1;
}
-bool GDBRemoteCommunicationClient::GetOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update) {
- if (GetHostInfo()) {
- if (m_os_version_major != UINT32_MAX) {
- major = m_os_version_major;
- minor = m_os_version_minor;
- update = m_os_version_update;
- return true;
- }
- }
- return false;
+llvm::VersionTuple GDBRemoteCommunicationClient::GetOSVersion() {
+ GetHostInfo();
+ return m_os_version;
}
bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) {
@@ -1199,9 +1206,7 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
// "version" key instead of
// "os_version"...
{
- Args::StringToVersion(value, m_os_version_major, m_os_version_minor,
- m_os_version_update);
- if (m_os_version_major != UINT32_MAX)
+ if (!m_os_version.tryParse(value))
++num_keys_decoded;
} else if (name.equals("watchpoint_exceptions_received")) {
m_watchpoints_trigger_after_instruction =
@@ -1451,7 +1456,8 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, response, false) ==
- PacketResult::Success) {
+ PacketResult::Success &&
+ response.GetResponseType() == StringExtractorGDBRemote::eResponse) {
llvm::StringRef name;
llvm::StringRef value;
addr_t addr_value = LLDB_INVALID_ADDRESS;
@@ -1527,8 +1533,134 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
if (m_supports_memory_region_info == eLazyBoolNo) {
error.SetErrorString("qMemoryRegionInfo is not supported");
}
- if (error.Fail())
- region_info.Clear();
+
+ // Try qXfer:memory-map:read to get region information not included in
+ // qMemoryRegionInfo
+ MemoryRegionInfo qXfer_region_info;
+ Status qXfer_error = GetQXferMemoryMapRegionInfo(addr, qXfer_region_info);
+
+ if (error.Fail()) {
+ // If qMemoryRegionInfo failed, but qXfer:memory-map:read succeeded, use
+ // the qXfer result as a fallback
+ if (qXfer_error.Success()) {
+ region_info = qXfer_region_info;
+ error.Clear();
+ } else {
+ region_info.Clear();
+ }
+ } else if (qXfer_error.Success()) {
+ // If both qMemoryRegionInfo and qXfer:memory-map:read succeeded, and if
+ // both regions are the same range, update the result to include the flash-
+ // memory information that is specific to the qXfer result.
+ if (region_info.GetRange() == qXfer_region_info.GetRange()) {
+ region_info.SetFlash(qXfer_region_info.GetFlash());
+ region_info.SetBlocksize(qXfer_region_info.GetBlocksize());
+ }
+ }
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::GetQXferMemoryMapRegionInfo(
+ lldb::addr_t addr, MemoryRegionInfo &region) {
+ Status error = LoadQXferMemoryMap();
+ if (!error.Success())
+ return error;
+ for (const auto &map_region : m_qXfer_memory_map) {
+ if (map_region.GetRange().Contains(addr)) {
+ region = map_region;
+ return error;
+ }
+ }
+ error.SetErrorString("Region not found");
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
+
+ Status error;
+
+ if (m_qXfer_memory_map_loaded)
+ // Already loaded, return success
+ return error;
+
+ if (!XMLDocument::XMLEnabled()) {
+ error.SetErrorString("XML is not supported");
+ return error;
+ }
+
+ if (!GetQXferMemoryMapReadSupported()) {
+ error.SetErrorString("Memory map is not supported");
+ return error;
+ }
+
+ std::string xml;
+ lldb_private::Status lldberr;
+ if (!ReadExtFeature(ConstString("memory-map"), ConstString(""), xml,
+ lldberr)) {
+ error.SetErrorString("Failed to read memory map");
+ return error;
+ }
+
+ XMLDocument xml_document;
+
+ if (!xml_document.ParseMemory(xml.c_str(), xml.size())) {
+ error.SetErrorString("Failed to parse memory map xml");
+ return error;
+ }
+
+ XMLNode map_node = xml_document.GetRootElement("memory-map");
+ if (!map_node) {
+ error.SetErrorString("Invalid root node in memory map xml");
+ return error;
+ }
+
+ m_qXfer_memory_map.clear();
+
+ map_node.ForEachChildElement([this](const XMLNode &memory_node) -> bool {
+ if (!memory_node.IsElement())
+ return true;
+ if (memory_node.GetName() != "memory")
+ return true;
+ auto type = memory_node.GetAttributeValue("type", "");
+ uint64_t start;
+ uint64_t length;
+ if (!memory_node.GetAttributeValueAsUnsigned("start", start))
+ return true;
+ if (!memory_node.GetAttributeValueAsUnsigned("length", length))
+ return true;
+ MemoryRegionInfo region;
+ region.GetRange().SetRangeBase(start);
+ region.GetRange().SetByteSize(length);
+ if (type == "rom") {
+ region.SetReadable(MemoryRegionInfo::eYes);
+ this->m_qXfer_memory_map.push_back(region);
+ } else if (type == "ram") {
+ region.SetReadable(MemoryRegionInfo::eYes);
+ region.SetWritable(MemoryRegionInfo::eYes);
+ this->m_qXfer_memory_map.push_back(region);
+ } else if (type == "flash") {
+ region.SetFlash(MemoryRegionInfo::eYes);
+ memory_node.ForEachChildElement(
+ [&region](const XMLNode &prop_node) -> bool {
+ if (!prop_node.IsElement())
+ return true;
+ if (prop_node.GetName() != "property")
+ return true;
+ auto propname = prop_node.GetAttributeValue("name", "");
+ if (propname == "blocksize") {
+ uint64_t blocksize;
+ if (prop_node.GetElementTextAsUnsigned(blocksize))
+ region.SetBlocksize(blocksize);
+ }
+ return true;
+ });
+ this->m_qXfer_memory_map.push_back(region);
+ }
+ return true;
+ });
+
+ m_qXfer_memory_map_loaded = true;
+
return error;
}
@@ -1585,13 +1717,13 @@ GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
Status error;
llvm::Triple::ArchType atype = arch.GetMachine();
- // we assume watchpoints will happen after running the relevant opcode
- // and we only want to override this behavior if we have explicitly
- // received a qHostInfo telling us otherwise
+ // we assume watchpoints will happen after running the relevant opcode and we
+ // only want to override this behavior if we have explicitly received a
+ // qHostInfo telling us otherwise
if (m_qHostInfo_is_valid != eLazyBoolYes) {
// On targets like MIPS and ppc64le, watchpoint exceptions are always
- // generated before the instruction is executed. The connected target
- // may not support qHostInfo or qWatchpointSupportInfo packets.
+ // generated before the instruction is executed. The connected target may
+ // not support qHostInfo or qWatchpointSupportInfo packets.
if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel ||
atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el ||
atype == llvm::Triple::ppc64le)
@@ -1789,11 +1921,12 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
process_info.GetArchitecture().SetTriple(triple.c_str());
} else if (name.equals("name")) {
StringExtractor extractor(value);
- // The process name from ASCII hex bytes since we can't
- // control the characters in a process name
+ // The process name from ASCII hex bytes since we can't control the
+ // characters in a process name
std::string name;
extractor.GetHexByteString(name);
- process_info.GetExecutableFile().SetFile(name, false);
+ process_info.GetExecutableFile().SetFile(name, false,
+ FileSpec::Style::native);
} else if (name.equals("cputype")) {
value.getAsInteger(0, cpu);
} else if (name.equals("cpusubtype")) {
@@ -2046,8 +2179,8 @@ uint32_t GDBRemoteCommunicationClient::FindProcesses(
}
}
StringExtractorGDBRemote response;
- // Increase timeout as the first qfProcessInfo packet takes a long time
- // on Android. The value of 1min was arrived at empirically.
+ // Increase timeout as the first qfProcessInfo packet takes a long time on
+ // Android. The value of 1min was arrived at empirically.
ScopedTimeout timeout(*this, minutes(1));
if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
PacketResult::Success) {
@@ -2081,8 +2214,8 @@ bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
- // the hex encoded user name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
+ // the hex encoded user name and should make up the entire packet. If
+ // there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString(name) * 2 ==
response.GetStringRef().size())
return true;
@@ -2108,8 +2241,8 @@ bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
PacketResult::Success) {
if (response.IsNormalResponse()) {
// Make sure we parsed the right number of characters. The response is
- // the hex encoded group name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
+ // the hex encoded group name and should make up the entire packet. If
+ // there are any non-hex ASCII bytes, the length won't match below..
if (response.GetHexByteString(name) * 2 ==
response.GetStringRef().size())
return true;
@@ -2335,8 +2468,8 @@ bool GDBRemoteCommunicationClient::LaunchGDBServer(
// Make the GDB server we launch only accept connections from this host
stream.Printf("host:%s;", hostname.c_str());
} else {
- // Make the GDB server we launch accept connections from any host since we
- // can't figure out the hostname
+ // Make the GDB server we launch accept connections from any host since
+ // we can't figure out the hostname
stream.Printf("host:*;");
}
}
@@ -2650,13 +2783,16 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
// process to exit
std::string
*command_output, // Pass NULL if you don't want the command output
- uint32_t
- timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
+ const Timeout<std::micro> &timeout) {
lldb_private::StreamString stream;
stream.PutCString("qPlatform_shell:");
stream.PutBytesAsRawHex8(command, strlen(command));
stream.PutChar(',');
+ uint32_t timeout_sec = UINT32_MAX;
+ if (timeout) {
+ // TODO: Use chrono version of std::ceil once c++17 is available.
+ timeout_sec = std::ceil(std::chrono::duration<double>(*timeout).count());
+ }
stream.PutHex32(timeout_sec);
if (working_dir) {
std::string path{working_dir.GetPath(false)};
@@ -3125,9 +3261,8 @@ bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
uint32_t save_id) {
// We use the "m_supports_QSaveRegisterState" variable here because the
- // QSaveRegisterState and QRestoreRegisterState packets must both be supported
- // in
- // order to be useful
+ // QSaveRegisterState and QRestoreRegisterState packets must both be
+ // supported in order to be useful
if (m_supports_QSaveRegisterState == eLazyBoolNo)
return false;
@@ -3406,7 +3541,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo(
StringExtractor extractor(value);
std::string uuid;
extractor.GetHexByteString(uuid);
- module_spec.GetUUID().SetFromCString(uuid.c_str(), uuid.size() / 2);
+ module_spec.GetUUID().SetFromStringRef(uuid, uuid.size() / 2);
} else if (name == "triple") {
StringExtractor extractor(value);
std::string triple;
@@ -3523,8 +3658,8 @@ GDBRemoteCommunicationClient::GetModulesInfo(
// query the target remote for extended information using the qXfer packet
//
-// example: object='features', annex='target.xml', out=<xml output>
-// return: 'true' on success
+// example: object='features', annex='target.xml', out=<xml output> return:
+// 'true' on success
// 'false' on failure (err set)
bool GDBRemoteCommunicationClient::ReadExtFeature(
const lldb_private::ConstString object,
@@ -3631,10 +3766,9 @@ bool GDBRemoteCommunicationClient::ReadExtFeature(
void GDBRemoteCommunicationClient::ServeSymbolLookups(
lldb_private::Process *process) {
- // Set to true once we've resolved a symbol to an address for the remote stub.
- // If we get an 'OK' response after this, the remote stub doesn't need any
- // more
- // symbols and we can stop asking.
+ // Set to true once we've resolved a symbol to an address for the remote
+ // stub. If we get an 'OK' response after this, the remote stub doesn't need
+ // any more symbols and we can stop asking.
bool symbol_response_provided = false;
// Is this the initial qSymbol:: packet?
@@ -3659,8 +3793,8 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
first_qsymbol_query = false;
if (response.IsUnsupportedResponse()) {
- // qSymbol is not supported by the current GDB server we are connected
- // to
+ // qSymbol is not supported by the current GDB server we are
+ // connected to
m_supports_qSymbol = false;
return;
} else {
@@ -3725,10 +3859,8 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
}
}
// This is the normal path where our symbol lookup was successful
- // and we want
- // to send a packet with the new symbol value and see if another
- // lookup needs to be
- // done.
+ // and we want to send a packet with the new symbol value and see
+ // if another lookup needs to be done.
// Change "packet" to contain the requested symbol value and name
packet.Clear();
@@ -3763,8 +3895,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
StructuredData::Array *
GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
if (!m_supported_async_json_packets_is_valid) {
- // Query the server for the array of supported asynchronous JSON
- // packets.
+ // Query the server for the array of supported asynchronous JSON packets.
m_supported_async_json_packets_is_valid = true;
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
@@ -3778,8 +3909,8 @@ GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
StructuredData::ParseJSON(response.GetStringRef());
if (m_supported_async_json_packets_sp &&
!m_supported_async_json_packets_sp->GetAsArray()) {
- // We were returned something other than a JSON array. This
- // is invalid. Clear it out.
+ // We were returned something other than a JSON array. This is
+ // invalid. Clear it out.
if (log)
log->Printf("GDBRemoteCommunicationClient::%s(): "
"QSupportedAsyncJSONPackets returned invalid "
@@ -3837,8 +3968,7 @@ Status GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
return error;
}
- // Build command: Configure{type_name}: serialized config
- // data.
+ // Build command: Configure{type_name}: serialized config data.
StreamGDBRemote stream;
stream.PutCString("QConfigure");
stream.PutCString(type_name.AsCString());
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index ba67b8246398..cf1d249768d7 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -121,6 +121,7 @@ public:
/// response was received.
//------------------------------------------------------------------
int SendEnvironmentPacket(char const *name_equal_value);
+ int SendEnvironment(const Environment &env);
int SendLaunchArchPacket(const char *arch);
@@ -265,7 +266,7 @@ public:
bool GetDefaultThreadId(lldb::tid_t &tid);
- bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);
+ llvm::VersionTuple GetOSVersion();
bool GetOSBuildString(std::string &s);
@@ -354,6 +355,8 @@ public:
bool GetQXferFeaturesReadSupported();
+ bool GetQXferMemoryMapReadSupported();
+
LazyBool SupportsAllocDeallocMemory() // const
{
// Uncomment this to have lldb pretend the debug server doesn't respond to
@@ -401,8 +404,7 @@ public:
// the process to exit
std::string
*command_output, // Pass nullptr if you don't want the command output
- uint32_t timeout_sec); // Timeout in seconds to wait for shell program to
- // finish
+ const Timeout<std::micro> &timeout);
bool CalculateMD5(const FileSpec &file_spec, uint64_t &high, uint64_t &low);
@@ -544,6 +546,7 @@ protected:
LazyBool m_supports_qXfer_libraries_read;
LazyBool m_supports_qXfer_libraries_svr4_read;
LazyBool m_supports_qXfer_features_read;
+ LazyBool m_supports_qXfer_memory_map_read;
LazyBool m_supports_augmented_libraries_svr4_read;
LazyBool m_supports_jThreadExtendedInfo;
LazyBool m_supports_jLoadedDynamicLibrariesInfos;
@@ -570,9 +573,7 @@ protected:
ArchSpec m_host_arch;
ArchSpec m_process_arch;
- uint32_t m_os_version_major;
- uint32_t m_os_version_minor;
- uint32_t m_os_version_update;
+ llvm::VersionTuple m_os_version;
std::string m_os_build;
std::string m_os_kernel;
std::string m_hostname;
@@ -587,6 +588,9 @@ protected:
bool m_supported_async_json_packets_is_valid;
lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp;
+ std::vector<MemoryRegionInfo> m_qXfer_memory_map;
+ bool m_qXfer_memory_map_loaded;
+
bool GetCurrentProcessInfo(bool allow_lazy_pid = true);
bool GetGDBServerVersion();
@@ -609,6 +613,11 @@ protected:
llvm::MutableArrayRef<uint8_t> &buffer,
size_t offset);
+ Status LoadQXferMemoryMap();
+
+ Status GetQXferMemoryMapRegionInfo(lldb::addr_t addr,
+ MemoryRegionInfo &region);
+
private:
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 4be92b79fd1a..4fc1fc7a1964 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -19,8 +19,8 @@
// Project includes
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index a35352480040..880caacd6414 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -57,8 +57,8 @@ protected:
bool m_exit_now; // use in asynchronous handling to indicate process should
// exit.
- bool m_send_error_strings; // If the client enables this then
- // we will send error strings as well.
+ bool m_send_error_strings = false; // If the client enables this then
+ // we will send error strings as well.
PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 3cf6b8ac07b2..c5b478378faa 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -28,7 +28,7 @@
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
@@ -36,13 +36,14 @@
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StreamGDBRemote.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/Triple.h"
// Project includes
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#ifdef __ANDROID__
#include "lldb/Host/android/HostInfoAndroid.h"
@@ -218,12 +219,15 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
if (sub != LLDB_INVALID_CPUTYPE)
response.Printf("cpusubtype:%u;", sub);
- if (cpu == ArchSpec::kCore_arm_any) {
+ if (cpu == llvm::MachO::CPU_TYPE_ARM
+ || cpu == llvm::MachO::CPU_TYPE_ARM64) {
// Indicate the OS type.
#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
response.PutCString("ostype:tvos;");
#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
response.PutCString("ostype:watchos;");
+#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
+ response.PutCString("ostype:bridgeos;");
#else
response.PutCString("ostype:ios;");
#endif
@@ -265,19 +269,10 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
break;
}
- uint32_t major = UINT32_MAX;
- uint32_t minor = UINT32_MAX;
- uint32_t update = UINT32_MAX;
- if (HostInfo::GetOSVersion(major, minor, update)) {
- if (major != UINT32_MAX) {
- response.Printf("os_version:%u", major);
- if (minor != UINT32_MAX) {
- response.Printf(".%u", minor);
- if (update != UINT32_MAX)
- response.Printf(".%u", update);
- }
- response.PutChar(';');
- }
+ llvm::VersionTuple version = HostInfo::GetOSVersion();
+ if (!version.empty()) {
+ response.Format("os_version:{0}", version.getAsString());
+ response.PutChar(';');
}
std::string s;
@@ -295,9 +290,9 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
#if defined(__APPLE__)
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
- // For iOS devices, we are connected through a USB Mux so we never pretend
- // to actually have a hostname as far as the remote lldb that is connecting
- // to this lldb-platform is concerned
+ // For iOS devices, we are connected through a USB Mux so we never pretend to
+ // actually have a hostname as far as the remote lldb that is connecting to
+ // this lldb-platform is concerned
response.PutCString("hostname:");
response.PutCStringAsRawHex8("127.0.0.1");
response.PutChar(';');
@@ -357,7 +352,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
StringExtractor extractor(value);
std::string file;
extractor.GetHexByteString(file);
- match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(
+ file, false, FileSpec::Style::native);
} else if (key.equals("name_match")) {
NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
.Case("equals", NameMatch::Equals)
@@ -401,7 +397,7 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
match_info.GetProcessInfo().SetEffectiveGroupID(gid);
} else if (key.equals("all_users")) {
match_info.SetMatchAllUsers(
- Args::StringToBoolean(value, false, &success));
+ OptionArgParser::ToBoolean(value, false, &success));
} else if (key.equals("triple")) {
match_info.GetProcessInfo().GetArchitecture() =
HostInfo::GetAugmentedArchSpec(value);
@@ -415,8 +411,8 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
}
if (Host::FindProcesses(match_info, m_proc_infos)) {
- // We found something, return the first item by calling the get
- // subsequent process info packet handler...
+ // We found something, return the first item by calling the get subsequent
+ // process info packet handler...
return Handle_qsProcessInfo(packet);
}
return SendErrorResponse(3);
@@ -731,14 +727,13 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
if (packet.GetChar() == ',') {
// FIXME: add timeout to qPlatform_shell packet
// uint32_t timeout = packet.GetHexMaxU32(false, 32);
- uint32_t timeout = 10;
if (packet.GetChar() == ',')
packet.GetHexByteString(working_dir);
int status, signo;
std::string output;
- Status err =
- Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true},
- &status, &signo, &output, timeout);
+ Status err = Host::RunShellCommand(
+ path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output,
+ std::chrono::seconds(10));
StreamGDBRemote response;
if (err.Fail()) {
response.PutCString("F,");
@@ -945,8 +940,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironment(
packet.SetFilePos(::strlen("QEnvironment:"));
const uint32_t bytes_left = packet.GetBytesLeft();
if (bytes_left > 0) {
- m_process_launch_info.GetEnvironmentEntries().AppendArgument(
- llvm::StringRef::withNullAsEmpty(packet.Peek()));
+ m_process_launch_info.GetEnvironment().insert(packet.Peek());
return SendOKResponse();
}
return SendErrorResponse(12);
@@ -960,7 +954,7 @@ GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded(
if (bytes_left > 0) {
std::string str;
packet.GetHexByteString(str);
- m_process_launch_info.GetEnvironmentEntries().AppendArgument(str);
+ m_process_launch_info.GetEnvironment().insert(str);
return SendOKResponse();
}
return SendErrorResponse(12);
@@ -981,11 +975,11 @@ GDBRemoteCommunicationServerCommon::Handle_QLaunchArch(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
- // The 'A' packet is the most over designed packet ever here with
- // redundant argument indexes, redundant argument lengths and needed hex
- // encoded argument string values. Really all that is needed is a comma
- // separated hex encoded argument value list, but we will stay true to the
- // documented version of the 'A' packet here...
+ // The 'A' packet is the most over designed packet ever here with redundant
+ // argument indexes, redundant argument lengths and needed hex encoded
+ // argument string values. Really all that is needed is a comma separated hex
+ // encoded argument value list, but we will stay true to the documented
+ // version of the 'A' packet here...
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
int actual_arg_index = 0;
@@ -993,8 +987,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
packet.SetFilePos(1); // Skip the 'A'
bool success = true;
while (success && packet.GetBytesLeft() > 0) {
- // Decode the decimal argument string length. This length is the
- // number of hex nibbles in the argument string value.
+ // Decode the decimal argument string length. This length is the number of
+ // hex nibbles in the argument string value.
const uint32_t arg_len = packet.GetU32(UINT32_MAX);
if (arg_len == UINT32_MAX)
success = false;
@@ -1003,8 +997,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (packet.GetChar() != ',')
success = false;
else {
- // Decode the argument index. We ignore this really because
- // who would really send down the arguments in a random order???
+ // Decode the argument index. We ignore this really because who would
+ // really send down the arguments in a random order???
const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
if (arg_idx == UINT32_MAX)
success = false;
@@ -1013,9 +1007,9 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (packet.GetChar() != ',')
success = false;
else {
- // Decode the argument string value from hex bytes
- // back into a UTF8 string and make sure the length
- // matches the one supplied in the packet
+ // Decode the argument string value from hex bytes back into a UTF8
+ // string and make sure the length matches the one supplied in the
+ // packet
std::string arg;
if (packet.GetHexByteStringFixedLength(arg, arg_len) !=
(arg_len / 2))
@@ -1029,7 +1023,8 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (success) {
if (arg_idx == 0)
- m_process_launch_info.GetExecutableFile().SetFile(arg, false);
+ m_process_launch_info.GetExecutableFile().SetFile(
+ arg, false, FileSpec::Style::native);
m_process_launch_info.GetArguments().AppendArgument(arg);
if (log)
log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"",
@@ -1254,8 +1249,8 @@ void GDBRemoteCommunicationServerCommon::
// Nothing.
break;
}
- // In case of MIPS64, pointer size is depend on ELF ABI
- // For N32 the pointer size is 4 and for N64 it is 8
+ // In case of MIPS64, pointer size is depend on ELF ABI For N32 the pointer
+ // size is 4 and for N64 it is 8
std::string abi = proc_arch.GetTargetABI();
if (!abi.empty())
response.Printf("elf_abi:%s;", abi.c_str());
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 32741c2404e2..50392fa38956 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -33,9 +33,9 @@
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
@@ -49,7 +49,7 @@
// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -236,16 +236,15 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
m_debugged_process_up = std::move(*process_or);
}
- // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol
- // as needed.
- // llgs local-process debugging may specify PTY paths, which will make these
- // file actions non-null
- // process launch -i/e/o will also make these file actions non-null
- // nullptr means that the traffic is expected to flow over gdb-remote protocol
+ // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as
+ // needed. llgs local-process debugging may specify PTY paths, which will
+ // make these file actions non-null process launch -i/e/o will also make
+ // these file actions non-null nullptr means that the traffic is expected to
+ // flow over gdb-remote protocol
if (should_forward_stdio) {
// nullptr means it's not redirected to file or pty (in case of LLGS local)
- // at least one of stdio will be transferred pty<->gdb-remote
- // we need to give the pty master handle to this object to read and/or write
+ // at least one of stdio will be transferred pty<->gdb-remote we need to
+ // give the pty master handle to this object to read and/or write
LLDB_LOG(log,
"pid = {0}: setting up stdout/stderr redirection via $O "
"gdb-remote commands",
@@ -291,7 +290,7 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
// else.
if (m_debugged_process_up &&
m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID)
- return Status("cannot attach to a process %" PRIu64
+ return Status("cannot attach to process %" PRIu64
" when another process with pid %" PRIu64
" is being debugged.",
pid, m_debugged_process_up->GetID());
@@ -410,8 +409,8 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
JSONObject::SP register_object_sp = std::make_shared<JSONObject>();
#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
- // Expedite all registers in the first register set (i.e. should be GPRs) that
- // are not contained in other registers.
+ // Expedite all registers in the first register set (i.e. should be GPRs)
+ // that are not contained in other registers.
const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
if (!reg_set_p)
return nullptr;
@@ -420,8 +419,7 @@ static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) {
uint32_t reg_num = *reg_num_p;
#else
// Expedite only a couple of registers until we figure out why sending
- // registers is
- // expensive.
+ // registers is expensive.
static const uint32_t k_expedited_registers[] = {
LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM};
@@ -595,8 +593,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
return SendErrorResponse(52);
// FIXME implement register handling for exec'd inferiors.
- // if (tid_stop_info.reason == eStopReasonExec)
- // {
+ // if (tid_stop_info.reason == eStopReasonExec) {
// const bool force = true;
// InitializeRegisters(force);
// }
@@ -633,14 +630,14 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutChar(';');
}
- // If a 'QListThreadsInStopReply' was sent to enable this feature, we
- // will send all thread IDs back in the "threads" key whose value is
- // a list of hex thread IDs separated by commas:
+ // If a 'QListThreadsInStopReply' was sent to enable this feature, we will
+ // send all thread IDs back in the "threads" key whose value is a list of hex
+ // thread IDs separated by commas:
// "threads:10a,10b,10c;"
- // This will save the debugger from having to send a pair of qfThreadInfo
- // and qsThreadInfo packets, but it also might take a lot of room in the
- // stop reply packet, so it must be enabled only on systems where there
- // are no limits on packet lengths.
+ // This will save the debugger from having to send a pair of qfThreadInfo and
+ // qsThreadInfo packets, but it also might take a lot of room in the stop
+ // reply packet, so it must be enabled only on systems where there are no
+ // limits on packet lengths.
if (m_list_threads_in_stop_reply) {
response.PutCString("threads:");
@@ -655,12 +652,11 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
}
response.PutChar(';');
- // Include JSON info that describes the stop reason for any threads
- // that actually have stop reasons. We use the new "jstopinfo" key
- // whose values is hex ascii JSON that contains the thread IDs
- // thread stop info only for threads that have stop reasons. Only send
- // this if we have more than one thread otherwise this packet has all
- // the info it needs.
+ // Include JSON info that describes the stop reason for any threads that
+ // actually have stop reasons. We use the new "jstopinfo" key whose values
+ // is hex ascii JSON that contains the thread IDs thread stop info only for
+ // threads that have stop reasons. Only send this if we have more than one
+ // thread otherwise this packet has all the info it needs.
if (thread_index > 0) {
const bool threads_with_valid_stop_info_only = true;
JSONArray::SP threads_info_sp = GetJSONThreadsInfo(
@@ -806,8 +802,8 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
__FUNCTION__, process->GetID());
}
- // Close the pipe to the inferior terminal i/o if we launched it
- // and set one up.
+ // Close the pipe to the inferior terminal i/o if we launched it and set one
+ // up.
MaybeCloseInferiorTerminalConnection();
// We are ready to exit the debug monitor.
@@ -823,8 +819,7 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
if (log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- // Send the stop reason unless this is the stop after the
- // launch or attach.
+ // Send the stop reason unless this is the stop after the launch or attach.
switch (m_inferior_prev_state) {
case eStateLaunching:
case eStateAttaching:
@@ -859,13 +854,11 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
break;
case StateType::eStateStopped:
- // Make sure we get all of the pending stdout/stderr from the inferior
- // and send it to the lldb host before we send the state change
- // notification
+ // Make sure we get all of the pending stdout/stderr from the inferior and
+ // send it to the lldb host before we send the state change notification
SendProcessOutput();
// Then stop the forwarding, so that any late output (see llvm.org/pr25652)
- // does not
- // interfere with our protocol.
+ // does not interfere with our protocol.
StopSTDIOForwarding();
HandleInferiorState_Stopped(process);
break;
@@ -1287,8 +1280,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
(m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID))
return SendErrorResponse(68);
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
+ // Make sure we set the current thread so g and p packets return the data the
+ // gdb will expect.
lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
SetCurrentThreadID(tid);
@@ -1397,10 +1390,9 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
Status error;
// We have two branches: what to do if a continue thread is specified (in
- // which case we target
- // sending the signal to that thread), or when we don't have a continue thread
- // set (in which
- // case we send a signal to the process).
+ // which case we target sending the signal to that thread), or when we don't
+ // have a continue thread set (in which case we send a signal to the
+ // process).
// TODO discuss with Greg Clayton, make sure this makes sense.
@@ -1639,8 +1631,8 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
case eStateStopped:
case eStateCrashed: {
lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID();
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
+ // Make sure we set the current thread so g and p packets return the data
+ // the gdb will expect.
SetCurrentThreadID(tid);
return SendStopReplyPacketForThread(tid);
}
@@ -2043,9 +2035,8 @@ GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
return SendErrorResponse(0x47);
}
- // The dwarf expression are evaluate on host site
- // which may cause register size to change
- // Hence the reg_size may not be same as reg_info->bytes_size
+ // The dwarf expression are evaluate on host site which may cause register
+ // size to change Hence the reg_size may not be same as reg_info->bytes_size
if ((reg_size != reg_info->byte_size) &&
!(reg_info->dynamic_size_dwarf_expr_bytes)) {
return SendIllFormedResponse(packet, "P packet register size is incorrect");
@@ -2376,10 +2367,9 @@ GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Currently only the NativeProcessProtocol knows if it can handle a
- // qMemoryRegionInfoSupported
- // request, but we're not guaranteed to be attached to a process. For now
- // we'll assume the
- // client only asks this when a process is being debugged.
+ // qMemoryRegionInfoSupported request, but we're not guaranteed to be
+ // attached to a process. For now we'll assume the client only asks this
+ // when a process is being debugged.
// Ensure we have a process running; otherwise, we can't figure this out
// since we won't have a NativeProcessProtocol.
@@ -2670,8 +2660,7 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
}
// We first try to use a continue thread id. If any one or any all set, use
- // the current thread.
- // Bail out if we don't have a thread id.
+ // the current thread. Bail out if we don't have a thread id.
lldb::tid_t tid = GetContinueThreadID();
if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
tid = GetCurrentThreadID();
@@ -2935,7 +2924,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach(
log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to "
"pid %" PRIu64 ": %s\n",
__FUNCTION__, pid, error.AsCString());
- return SendErrorResponse(0x01);
+ return SendErrorResponse(error);
}
// Notify we attached by sending a stop packet.
@@ -3093,8 +3082,8 @@ GDBRemoteCommunicationServerLLGS::Handle_QPassSignals(
std::vector<int> signals;
packet.SetFilePos(strlen("QPassSignals:"));
- // Read sequence of hex signal numbers divided by a semicolon and
- // optionally spaces.
+ // Read sequence of hex signal numbers divided by a semicolon and optionally
+ // spaces.
while (packet.GetBytesLeft() > 0) {
int signal = packet.GetS32(-1, 16);
if (signal < 0)
@@ -3154,8 +3143,7 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
return nullptr;
// If the client hasn't asked for thread suffix support, there will not be a
- // thread suffix.
- // Use the current thread in that case.
+ // thread suffix. Use the current thread in that case.
if (!m_thread_suffix_supported) {
const lldb::tid_t current_tid = GetCurrentThreadID();
if (current_tid == LLDB_INVALID_THREAD_ID)
@@ -3201,9 +3189,9 @@ NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
- // Use whatever the debug process says is the current thread id
- // since the protocol either didn't specify or specified we want
- // any/all threads marked as the current thread.
+ // Use whatever the debug process says is the current thread id since the
+ // protocol either didn't specify or specified we want any/all threads
+ // marked as the current thread.
if (!m_debugged_process_up)
return LLDB_INVALID_THREAD_ID;
return m_debugged_process_up->GetCurrentThreadID();
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 04ed9d704e13..26e28a900320 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -14,6 +14,7 @@
// C Includes
// C++ Includes
#include <chrono>
+#include <csignal>
#include <cstring>
#include <mutex>
#include <sstream>
@@ -38,7 +39,7 @@
#include "lldb/Utility/UriParser.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -101,11 +102,11 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
if (port == UINT16_MAX)
port = GetNextAvailablePort();
- // Spawn a new thread to accept the port that gets bound after
- // binding to port 0 (zero).
+ // Spawn a new thread to accept the port that gets bound after binding to
+ // port 0 (zero).
- // ignore the hostname send from the remote end, just use the ip address
- // that we're currently communicating with as the hostname
+ // ignore the hostname send from the remote end, just use the ip address that
+ // we're currently communicating with as the hostname
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
@@ -116,8 +117,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
if (log)
log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
- // Do not run in a new session so that it can not linger after the
- // platform closes.
+ // Do not run in a new session so that it can not linger after the platform
+ // closes.
debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
debugserver_launch_info.SetMonitorProcessCallback(
std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
@@ -170,8 +171,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
#ifdef _WIN32
return SendErrorResponse(9);
#else
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
+ // Spawn a local debugserver as a platform so we can then attach or launch a
+ // process...
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
@@ -259,8 +260,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
- // verify that we know anything about this pid.
- // Scope for locker
+ // verify that we know anything about this pid. Scope for locker
{
std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
@@ -306,8 +306,8 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
return true;
}
- // the launched process still lives. Now try killing it again,
- // this time with an unblockable signal.
+ // the launched process still lives. Now try killing it again, this time
+ // with an unblockable signal.
Host::Kill(pid, SIGKILL);
for (size_t i = 0; i < 10; ++i) {
@@ -321,8 +321,7 @@ bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
usleep(10000);
}
- // check one more time after the final usleep
- // Scope for locker
+ // check one more time after the final usleep Scope for locker
{
std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
@@ -389,14 +388,13 @@ GDBRemoteCommunicationServerPlatform::Handle_qC(
StreamString response;
response.Printf("QC%" PRIx64, pid);
- // If we launch a process and this GDB server is acting as a platform,
- // then we need to clear the process launch state so we can start
- // launching another process. In order to launch a process a bunch or
- // packets need to be sent: environment packets, working directory,
- // disable ASLR, and many more settings. When we launch a process we
- // then need to know when to clear this information. Currently we are
- // selecting the 'qC' packet as that packet which seems to make the most
- // sense.
+ // If we launch a process and this GDB server is acting as a platform, then
+ // we need to clear the process launch state so we can start launching
+ // another process. In order to launch a process a bunch or packets need to
+ // be sent: environment packets, working directory, disable ASLR, and many
+ // more settings. When we launch a process we then need to know when to clear
+ // this information. Currently we are selecting the 'qC' packet as that
+ // packet which seems to make the most sense.
if (pid != LLDB_INVALID_PROCESS_ID) {
m_process_launch_info.Clear();
}
@@ -445,9 +443,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
return Status("%s: no process command line specified to launch",
__FUNCTION__);
- // specify the process monitor if not already set. This should
- // generally be what happens since we need to reap started
- // processes.
+ // specify the process monitor if not already set. This should generally be
+ // what happens since we need to reap started processes.
if (!m_process_launch_info.GetMonitorProcessCallback())
m_process_launch_info.SetMonitorProcessCallback(
std::bind(
@@ -466,8 +463,8 @@ Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
m_process_launch_info.GetProcessID());
- // add to list of spawned processes. On an lldb-gdbserver, we
- // would expect there to be only one.
+ // add to list of spawned processes. On an lldb-gdbserver, we would expect
+ // there to be only one.
const auto pid = m_process_launch_info.GetProcessID();
if (pid != LLDB_INVALID_PROCESS_ID) {
// add to spawned pids
@@ -537,7 +534,7 @@ const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
if (domainsocket_dir_env != nullptr)
g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
else
- HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
+ g_domainsocket_dir = HostInfo::GetProcessTempDir();
});
return g_domainsocket_dir;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index e418deee01f3..07dab751f4b9 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -25,7 +25,7 @@
#include "ThreadGDBRemote.h"
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -39,9 +39,9 @@ GDBRemoteRegisterContext::GDBRemoteRegisterContext(
GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once)
: RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) {
- // Resize our vector of bools to contain one bool for every register.
- // We will use these boolean values to know when a register value
- // is valid in m_reg_data.
+ // Resize our vector of bools to contain one bool for every register. We will
+ // use these boolean values to know when a register value is valid in
+ // m_reg_data.
m_reg_valid.resize(reg_info.GetNumRegisters());
// Make a heap based buffer that is big enough to store all registers
@@ -119,8 +119,8 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(
if (success) {
SetRegisterIsValid(reg, true);
} else if (data.size() > 0) {
- // Only set register is valid to false if we copied some bytes, else
- // leave it as it was.
+ // Only set register is valid to false if we copied some bytes, else leave
+ // it as it was.
SetRegisterIsValid(reg, false);
}
return success;
@@ -133,11 +133,9 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
return false;
// Early in process startup, we can get a thread that has an invalid byte
- // order
- // because the process hasn't been completely set up yet (see the ctor where
- // the
- // byte order is setfrom the process). If that's the case, we can't set the
- // value here.
+ // order because the process hasn't been completely set up yet (see the ctor
+ // where the byte order is setfrom the process). If that's the case, we
+ // can't set the value here.
if (m_reg_data.GetByteOrder() == eByteOrderInvalid) {
return false;
}
@@ -149,8 +147,7 @@ bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
DataExtractor data(buffer_sp, endian::InlHostByteOrder(), sizeof(void *));
// If our register context and our register info disagree, which should never
- // happen, don't
- // overwrite past the end of the buffer.
+ // happen, don't overwrite past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
@@ -219,8 +216,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
}
if (reg_info->value_regs) {
// Process this composite register request by delegating to the
- // constituent
- // primordial registers.
+ // constituent primordial registers.
// Index of the primordial register.
bool success = true;
@@ -228,8 +224,8 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
const uint32_t prim_reg = reg_info->value_regs[idx];
if (prim_reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
+ // We have a valid primordial register as our constituent. Grab the
+ // corresponding register info.
const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
if (prim_reg_info == NULL)
success = false;
@@ -242,8 +238,7 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
if (success) {
// If we reach this point, all primordial register requests have
- // succeeded.
- // Validate this composite register.
+ // succeeded. Validate this composite register.
SetRegisterIsValid(reg_info, true);
}
} else {
@@ -262,16 +257,14 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
reg_info->byte_offset + reg_info->byte_size);
#endif
// If our register context and our register info disagree, which should
- // never happen, don't
- // read past the end of the buffer.
+ // never happen, don't read past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
- // If we aren't extracting into our own buffer (which
- // only happens when this function is called from
- // ReadRegisterValue(uint32_t, Scalar&)) then
- // we transfer bytes from our buffer into the data
- // buffer that was passed in
+ // If we aren't extracting into our own buffer (which only happens when
+ // this function is called from ReadRegisterValue(uint32_t, Scalar&)) then
+ // we transfer bytes from our buffer into the data buffer that was passed
+ // in
data.SetByteOrder(m_reg_data.GetByteOrder());
data.SetData(m_reg_data, reg_info->byte_offset, reg_info->byte_size);
@@ -321,8 +314,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
#endif
// If our register context and our register info disagree, which should never
- // happen, don't
- // overwrite past the end of the buffer.
+ // happen, don't overwrite past the end of the buffer.
if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
return false;
@@ -358,12 +350,10 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
bool success = true;
if (reg_info->value_regs) {
- // This register is part of another register. In this case we read the
- // actual
- // register data for any "value_regs", and once all that data is read,
- // we will
- // have enough data in our register context bytes for the value of
- // this register
+ // This register is part of another register. In this case we read
+ // the actual register data for any "value_regs", and once all that
+ // data is read, we will have enough data in our register context
+ // bytes for the value of this register
// Invalidate this composite register first.
@@ -371,8 +361,8 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
const uint32_t reg = reg_info->value_regs[idx];
if (reg == LLDB_INVALID_REGNUM)
break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
+ // We have a valid primordial register as our constituent. Grab the
+ // corresponding register info.
const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
if (value_reg_info == NULL)
success = false;
@@ -385,8 +375,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
}
// Check if writing this register will invalidate any other register
- // values?
- // If so, invalidate them
+ // values? If so, invalidate them
if (reg_info->invalidate_regs) {
for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
reg != LLDB_INVALID_REGNUM;
@@ -548,26 +537,22 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
return true;
uint32_t num_restored = 0;
- // We need to manually go through all of the registers and
- // restore them manually
+ // We need to manually go through all of the registers and restore them
+ // manually
DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(),
m_reg_data.GetAddressByteSize());
const RegisterInfo *reg_info;
- // The g packet contents may either include the slice registers (registers
- // defined in
- // terms of other registers, e.g. eax is a subset of rax) or not. The
- // slice registers
- // should NOT be in the g packet, but some implementations may incorrectly
- // include them.
+ // The g packet contents may either include the slice registers
+ // (registers defined in terms of other registers, e.g. eax is a subset
+ // of rax) or not. The slice registers should NOT be in the g packet,
+ // but some implementations may incorrectly include them.
//
// If the slice registers are included in the packet, we must step over
- // the slice registers
- // when parsing the packet -- relying on the RegisterInfo byte_offset
- // field would be incorrect.
- // If the slice registers are not included, then using the byte_offset
- // values into the
+ // the slice registers when parsing the packet -- relying on the
+ // RegisterInfo byte_offset field would be incorrect. If the slice
+ // registers are not included, then using the byte_offset values into the
// data buffer is the best way to find individual register values.
uint64_t size_including_slice_registers = 0;
@@ -591,21 +576,17 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
} else if (size_not_including_slice_registers ==
restore_data.GetByteSize()) {
// The size of the packet is the same as concatenating all of the
- // registers sequentially,
- // skipping the slice registers
+ // registers sequentially, skipping the slice registers
use_byte_offset_into_buffer = true;
} else if (size_including_slice_registers == restore_data.GetByteSize()) {
// The slice registers are present in the packet (when they shouldn't
- // be).
- // Don't try to use the RegisterInfo byte_offset into the restore_data,
- // it will
- // point to the wrong place.
+ // be). Don't try to use the RegisterInfo byte_offset into the
+ // restore_data, it will point to the wrong place.
use_byte_offset_into_buffer = false;
} else {
// None of our expected sizes match the actual g packet data we're
- // looking at.
- // The most conservative approach here is to use the running total byte
- // offset.
+ // looking at. The most conservative approach here is to use the
+ // running total byte offset.
use_byte_offset_into_buffer = false;
}
@@ -664,11 +645,9 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
if (reg_info->value_regs) // skip registers that are slices of real
// registers
continue;
- // Skip the fpsr and fpcr floating point status/control register writing
- // to
- // work around a bug in an older version of debugserver that would lead
- // to
- // register context corruption when writing fpsr/fpcr.
+ // Skip the fpsr and fpcr floating point status/control register
+ // writing to work around a bug in an older version of debugserver that
+ // would lead to register context corruption when writing fpsr/fpcr.
if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 ||
strcmp(reg_info->name, "fpcr") == 0)) {
continue;
@@ -752,8 +731,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
static uint32_t g_q14_regs[] = {71, 72, LLDB_INVALID_REGNUM}; // (d28, d29)
static uint32_t g_q15_regs[] = {73, 74, LLDB_INVALID_REGNUM}; // (d30, d31)
- // This is our array of composite registers, with each element coming from the
- // above register mappings.
+ // This is our array of composite registers, with each element coming from
+ // the above register mappings.
static uint32_t *g_composites[] = {
g_d0_regs, g_d1_regs, g_d2_regs, g_d3_regs, g_d4_regs, g_d5_regs,
g_d6_regs, g_d7_regs, g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs,
@@ -884,21 +863,17 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
if (from_scratch) {
// Calculate the offsets of the registers
// Note that the layout of the "composite" registers (d0-d15 and q0-q15)
- // which comes after the
- // "primordial" registers is important. This enables us to calculate the
- // offset of the composite
- // register by using the offset of its first primordial register. For
- // example, to calculate the
- // offset of q0, use s0's offset.
+ // which comes after the "primordial" registers is important. This enables
+ // us to calculate the offset of the composite register by using the offset
+ // of its first primordial register. For example, to calculate the offset
+ // of q0, use s0's offset.
if (g_register_infos[2].byte_offset == 0) {
uint32_t byte_offset = 0;
for (i = 0; i < num_registers; ++i) {
// For primordial registers, increment the byte_offset by the byte_size
- // to arrive at the
- // byte_offset for the next register. Otherwise, we have a composite
- // register whose
- // offset can be calculated by consulting the offset of its first
- // primordial register.
+ // to arrive at the byte_offset for the next register. Otherwise, we
+ // have a composite register whose offset can be calculated by
+ // consulting the offset of its first primordial register.
if (!g_register_infos[i].value_regs) {
g_register_infos[i].byte_offset = byte_offset;
byte_offset += g_register_infos[i].byte_size;
@@ -933,8 +908,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
// First we need to validate that all registers that we already have match
- // the non composite regs.
- // If so, then we can add the registers, else we need to bail
+ // the non composite regs. If so, then we can add the registers, else we
+ // need to bail
bool match = true;
if (num_dynamic_regs == num_common_regs) {
for (i = 0; match && i < num_dynamic_regs; ++i) {
@@ -970,9 +945,8 @@ void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
// Find a matching primordial register info entry.
if (reg_info && reg_info->name &&
::strcasecmp(reg_info->name, reg_name) == 0) {
- // The name matches the existing primordial entry.
- // Find and assign the offset, and then add this composite
- // register entry.
+ // The name matches the existing primordial entry. Find and
+ // assign the offset, and then add this composite register entry.
g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
name.SetCString(g_comp_register_infos[i].name);
AddRegister(g_comp_register_infos[i], name, alt_name,
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 35d02c15ab85..b3d33b19bd66 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -24,6 +24,7 @@
// C++ Includes
#include <algorithm>
+#include <csignal>
#include <map>
#include <mutex>
#include <sstream>
@@ -46,11 +47,11 @@
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/XML.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/OptionValueProperties.h"
@@ -59,10 +60,12 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Utility/Args.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/StreamString.h"
@@ -77,8 +80,8 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
-#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Host/Host.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Threading.h"
@@ -91,11 +94,11 @@ using namespace lldb_private::process_gdb_remote;
namespace lldb {
// Provide a function that can easily dump the packet history if we know a
-// ProcessGDBRemote * value (which we can get from logs or from debugging).
-// We need the function in the lldb namespace so it makes it into the final
+// ProcessGDBRemote * value (which we can get from logs or from debugging). We
+// need the function in the lldb namespace so it makes it into the final
// executable since the LLDB shared library only exports stuff in the lldb
-// namespace. This allows you to attach with a debugger and call this
-// function and get the packet history dumped to a file.
+// namespace. This allows you to attach with a debugger and call this function
+// and get the packet history dumped to a file.
void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
StreamFile strm;
Status error(strm.GetFile().Open(path, File::eOpenOptionWrite |
@@ -158,8 +161,8 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
} // anonymous namespace end
// TODO Randomly assigning a port is unsafe. We should get an unused
-// ephemeral port from the kernel and make sure we reserve it before passing
-// it to debugserver.
+// ephemeral port from the kernel and make sure we reserve it before passing it
+// to debugserver.
#if defined(__APPLE__)
#define LOW_PORT (IPPORT_RESERVED)
@@ -233,8 +236,8 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
}
return exe_module->GetFileSpec().Exists();
}
- // However, if there is no executable module, we return true since we might be
- // preparing to attach.
+ // However, if there is no executable module, we return true since we might
+ // be preparing to attach.
return true;
}
@@ -256,7 +259,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
m_addr_to_mmap_size(), m_thread_create_bp_sp(),
m_waiting_for_attach(false), m_destroy_tried_resuming(false),
m_command_sp(), m_breakpoint_pc_offset(0),
- m_initial_tid(LLDB_INVALID_THREAD_ID) {
+ m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false),
+ m_erased_flash_ranges() {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
"async thread should exit");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
@@ -299,17 +303,16 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
ProcessGDBRemote::~ProcessGDBRemote() {
// m_mach_process.UnregisterNotificationCallbacks (this);
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
- // The general Finalize is going to try to destroy the process and that SHOULD
- // shut down the async thread. However, if we don't kill it it will get
- // stranded and
- // its connection will go away so when it wakes up it will crash. So kill it
- // for sure here.
+ // The general Finalize is going to try to destroy the process and that
+ // SHOULD shut down the async thread. However, if we don't kill it it will
+ // get stranded and its connection will go away so when it wakes up it will
+ // crash. So kill it for sure here.
StopAsyncThread();
KillDebugserverProcess();
}
@@ -368,8 +371,7 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition(
}
// If the remote stub didn't give us eh_frame or DWARF register numbers for a
-// register,
-// see if the ABI can provide them.
+// register, see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
ConstString reg_name, ABISP abi_sp) {
@@ -422,9 +424,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
m_register_info.Clear();
- // Check if qHostInfo specified a specific packet timeout for this connection.
- // If so then lets update our setting so the user knows what the timeout is
- // and can see it.
+ // Check if qHostInfo specified a specific packet timeout for this
+ // connection. If so then lets update our setting so the user knows what the
+ // timeout is and can see it.
const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
if (host_packet_timeout > std::chrono::seconds(0)) {
GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout.count());
@@ -531,7 +533,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
reg_info.encoding = encoding;
} else if (name.equals("format")) {
Format format = eFormatInvalid;
- if (Args::StringToFormat(value.str().c_str(), format, NULL)
+ if (OptionArgParser::ToFormat(value.str().c_str(), format, NULL)
.Success())
reg_info.format = format;
else {
@@ -596,10 +598,8 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
}
// We have to make a temporary ABI here, and not use the GetABI because
- // this code
- // gets called in DidAttach, when the target architecture (and
- // consequently the ABI we'll get from
- // the process) may be wrong.
+ // this code gets called in DidAttach, when the target architecture
+ // (and consequently the ABI we'll get from the process) may be wrong.
ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use);
AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
@@ -620,9 +620,9 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
// We didn't get anything if the accumulated reg_num is zero. See if we are
// debugging ARM and fill with a hard coded register set until we can get an
- // updated debugserver down on the devices.
- // On the other hand, if the accumulated reg_num is positive, see if we can
- // add composite registers to the existing primordial ones.
+ // updated debugserver down on the devices. On the other hand, if the
+ // accumulated reg_num is positive, see if we can add composite registers to
+ // the existing primordial ones.
bool from_scratch = (m_register_info.GetNumRegisters() == 0);
if (!target_arch.IsValid()) {
@@ -669,9 +669,8 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
if (pid == LLDB_INVALID_PROCESS_ID) {
- // We don't have a valid process ID, so note that we are connected
- // and could now request to launch or attach, or get remote process
- // listings...
+ // We don't have a valid process ID, so note that we are connected and
+ // could now request to launch or attach, or get remote process listings...
SetPrivateState(eStateConnected);
} else {
// We have a valid process
@@ -721,7 +720,8 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
if (error.Success() && !GetTarget().GetArchitecture().IsValid() &&
m_gdb_comm.GetHostArchitecture().IsValid()) {
- // Prefer the *process'* architecture over that of the *host*, if available.
+ // Prefer the *process'* architecture over that of the *host*, if
+ // available.
if (m_gdb_comm.GetProcessArchitecture().IsValid())
GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
else
@@ -800,8 +800,8 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
if (stdin_file_spec || disable_stdio) {
- // the inferior will be reading stdin from the specified file
- // or stdio is completely disabled
+ // the inferior will be reading stdin from the specified file or stdio is
+ // completely disabled
m_stdin_forward = false;
} else {
m_stdin_forward = true;
@@ -824,11 +824,14 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
if (disable_stdio) {
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
- stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
if (!stdout_file_spec)
- stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
if (!stderr_file_spec)
- stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ FileSpec::Style::native);
} else if (platform_sp && platform_sp->IsHost()) {
// If the debugserver is local and we aren't disabling STDIO, lets use
// a pseudo terminal to instead of relying on the 'O' packets for stdio
@@ -888,16 +891,7 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
}
// Send the environment and the program + arguments after we connect
- const Args &environment = launch_info.GetEnvironmentEntries();
- if (environment.GetArgumentCount()) {
- size_t num_environment_entries = environment.GetArgumentCount();
- for (size_t i = 0; i < num_environment_entries; ++i) {
- const char *env_entry = environment.GetArgumentAtIndex(i);
- if (env_entry == NULL ||
- m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
- break;
- }
- }
+ m_gdb_comm.SendEnvironment(launch_info.GetEnvironment());
{
// Scope for the scoped timeout object
@@ -1004,16 +998,15 @@ Status ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
return error;
}
- // Start the communications read thread so all incoming data can be
- // parsed into packets and queued as they arrive.
+ // Start the communications read thread so all incoming data can be parsed
+ // into packets and queued as they arrive.
if (GetTarget().GetNonStopModeEnabled())
m_gdb_comm.StartReadThread();
- // We always seem to be able to open a connection to a local port
- // so we need to make sure we can then send data to it. If we can't
- // then we aren't actually connected to anything, so try and do the
- // handshake with the remote GDB server and make sure that goes
- // alright.
+ // We always seem to be able to open a connection to a local port so we need
+ // to make sure we can then send data to it. If we can't then we aren't
+ // actually connected to anything, so try and do the handshake with the
+ // remote GDB server and make sure that goes alright.
if (!m_gdb_comm.HandshakeWithServer(&error)) {
m_gdb_comm.Disconnect();
if (error.Success())
@@ -1055,9 +1048,9 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
// See if the GDB server supports the qHostInfo information
- // See if the GDB server supports the qProcessInfo packet, if so
- // prefer that over the Host information as it will be more specific
- // to our process.
+ // See if the GDB server supports the qProcessInfo packet, if so prefer
+ // that over the Host information as it will be more specific to our
+ // process.
const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
if (remote_process_arch.IsValid()) {
@@ -1102,9 +1095,8 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
// architectures.
// You can have an armv6 executable, and if the host is armv7, then the
// system will load the best possible architecture for all shared
- // libraries
- // it has, so we really need to take the remote host architecture as our
- // defacto architecture in this case.
+ // libraries it has, so we really need to take the remote host
+ // architecture as our defacto architecture in this case.
if ((process_arch.GetMachine() == llvm::Triple::arm ||
process_arch.GetMachine() == llvm::Triple::thumb) &&
@@ -1150,14 +1142,14 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
? target_arch.GetTriple().getTriple().c_str()
: "<null>");
} else {
- // The target doesn't have a valid architecture yet, set it from
- // the architecture we got from the remote GDB server
+ // The target doesn't have a valid architecture yet, set it from the
+ // architecture we got from the remote GDB server
GetTarget().SetArchitecture(process_arch);
}
}
- // Find out which StructuredDataPlugins are supported by the
- // debug monitor. These plugins transmit data over async $J packets.
+ // Find out which StructuredDataPlugins are supported by the debug monitor.
+ // These plugins transmit data over async $J packets.
auto supported_packets_array =
m_gdb_comm.GetSupportedStructuredDataPlugins();
if (supported_packets_array)
@@ -1365,9 +1357,9 @@ Status ProcessGDBRemote::DoResume() {
continue_packet_error = true;
if (continue_packet_error) {
- // Either no vCont support, or we tried to use part of the vCont
- // packet that wasn't supported by the remote GDB server.
- // We need to try and make a simple packet that can do our continue
+ // Either no vCont support, or we tried to use part of the vCont packet
+ // that wasn't supported by the remote GDB server. We need to try and
+ // make a simple packet that can do our continue
const size_t num_continue_c_tids = m_continue_c_tids.size();
const size_t num_continue_C_tids = m_continue_C_tids.size();
const size_t num_continue_s_tids = m_continue_s_tids.size();
@@ -1394,11 +1386,10 @@ Status ProcessGDBRemote::DoResume() {
const int continue_signo = m_continue_C_tids.front().second;
// Only one thread is continuing
if (num_continue_C_tids > 1) {
- // More that one thread with a signal, yet we don't have
- // vCont support and we are being asked to resume each
- // thread with a signal, we need to make sure they are
- // all the same signal, or we can't issue the continue
- // accurately with the current support...
+ // More that one thread with a signal, yet we don't have vCont
+ // support and we are being asked to resume each thread with a
+ // signal, we need to make sure they are all the same signal, or we
+ // can't issue the continue accurately with the current support...
if (num_continue_C_tids > 1) {
continue_packet_error = false;
for (size_t i = 1; i < m_continue_C_tids.size(); ++i) {
@@ -1532,7 +1523,6 @@ void ProcessGDBRemote::ClearThreadIDList() {
size_t
ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) {
m_thread_ids.clear();
- m_thread_pcs.clear();
size_t comma_pos;
lldb::tid_t tid;
while ((comma_pos = value.find(',')) != std::string::npos) {
@@ -1675,9 +1665,8 @@ bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
}
}
- // Whatever that is left in old_thread_list_copy are not
- // present in new_thread_list. Remove non-existent threads from internal id
- // table.
+ // Whatever that is left in old_thread_list_copy are not present in
+ // new_thread_list. Remove non-existent threads from internal id table.
size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
for (size_t i = 0; i < old_num_thread_ids; i++) {
ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
@@ -1738,12 +1727,11 @@ bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
return true;
// See if we got thread stop info for any threads valid stop info reasons
- // threads
- // via the "jstopinfo" packet stop reply packet key/value pair?
+ // threads via the "jstopinfo" packet stop reply packet key/value pair?
if (m_jstopinfo_sp) {
// If we have "jstopinfo" then we have stop descriptions for all threads
- // that have stop reasons, and if there is no entry for a thread, then
- // it has no stop reason.
+ // that have stop reasons, and if there is no entry for a thread, then it
+ // has no stop reason.
thread->GetRegisterContext()->InvalidateIfNeeded(true);
if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) {
thread->SetStopInfo(StopInfoSP());
@@ -1771,9 +1759,8 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (tid != LLDB_INVALID_THREAD_ID) {
// Scope for "locker" below
{
- // m_thread_list_real does have its own mutex, but we need to
- // hold onto the mutex between the call to
- // m_thread_list_real.FindThreadByID(...)
+ // m_thread_list_real does have its own mutex, but we need to hold onto
+ // the mutex between the call to m_thread_list_real.FindThreadByID(...)
// and the m_thread_list_real.AddThread(...) so it doesn't change on us
std::lock_guard<std::recursive_mutex> guard(
m_thread_list_real.GetMutex());
@@ -1827,10 +1814,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (!thread_sp->StopInfoIsUpToDate()) {
thread_sp->SetStopInfo(StopInfoSP());
// If there's a memory thread backed by this thread, we need to use it
- // to calcualte StopInfo.
- ThreadSP memory_thread_sp =
- m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
- if (memory_thread_sp)
+ // to calculate StopInfo.
+ if (ThreadSP memory_thread_sp =
+ m_thread_list.GetBackingThread(thread_sp))
thread_sp = memory_thread_sp;
if (exc_type != 0) {
@@ -1852,9 +1838,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
->GetBreakpointSiteList()
.FindByAddress(pc);
- // If the current pc is a breakpoint site then the StopInfo should
- // be set to Breakpoint
- // Otherwise, it will be set to Trace.
+ // If the current pc is a breakpoint site then the StopInfo
+ // should be set to Breakpoint Otherwise, it will be set to
+ // Trace.
if (bp_site_sp &&
bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
@@ -1871,11 +1857,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
.FindByAddress(pc);
if (bp_site_sp) {
// If the breakpoint is for this thread, then we'll report the
- // hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices
- // that there's a breakpoint under the pc.
+ // hit, but if it is for another thread, we can just report no
+ // reason. We don't need to worry about stepping over the
+ // breakpoint here, that will be taken care of when the thread
+ // resumes and notices that there's a breakpoint under the pc.
handled = true;
if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
@@ -1937,13 +1922,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
pc);
// If the current pc is a breakpoint site then the StopInfo should
- // be set to Breakpoint
- // even though the remote stub did not set it as such. This can
- // happen when
- // the thread is involuntarily interrupted (e.g. due to stops on
- // other
- // threads) just as it is about to execute the breakpoint
- // instruction.
+ // be set to Breakpoint even though the remote stub did not set it
+ // as such. This can happen when the thread is involuntarily
+ // interrupted (e.g. due to stops on other threads) just as it is
+ // about to execute the breakpoint instruction.
if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithBreakpointSiteID(
@@ -1965,11 +1947,10 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (bp_site_sp) {
// If the breakpoint is for this thread, then we'll report the
- // hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about
- // stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices
- // that there's a breakpoint under the pc.
+ // hit, but if it is for another thread, we can just report no
+ // reason. We don't need to worry about stepping over the
+ // breakpoint here, that will be taken care of when the thread
+ // resumes and notices that there's a breakpoint under the pc.
if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
if (m_breakpoint_pc_offset != 0)
thread_sp->GetRegisterContext()->SetPC(pc);
@@ -1982,8 +1963,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
}
} else {
// If we were stepping then assume the stop was the result of
- // the trace. If we were
- // not stepping then report the SIGTRAP.
+ // the trace. If we were not stepping then report the SIGTRAP.
// FIXME: We are still missing the case where we single step
// over a trap instruction.
if (thread_sp->GetTemporaryResumeState() == eStateStepping)
@@ -2178,15 +2158,15 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
switch (stop_type) {
case 'T':
case 'S': {
- // This is a bit of a hack, but is is required. If we did exec, we
- // need to clear our thread lists and also know to rebuild our dynamic
- // register info before we lookup and threads and populate the expedited
- // register values so we need to know this right away so we can cleanup
- // and update our registers.
+ // This is a bit of a hack, but is is required. If we did exec, we need to
+ // clear our thread lists and also know to rebuild our dynamic register
+ // info before we lookup and threads and populate the expedited register
+ // values so we need to know this right away so we can cleanup and update
+ // our registers.
const uint32_t stop_id = GetStopID();
if (stop_id == 0) {
- // Our first stop, make sure we have a process ID, and also make
- // sure we know about our registers
+ // Our first stop, make sure we have a process ID, and also make sure we
+ // know about our registers
if (GetID() == LLDB_INVALID_PROCESS_ID) {
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
if (pid != LLDB_INVALID_PROCESS_ID)
@@ -2232,8 +2212,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
m_thread_ids.clear();
// A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
+ // process that includes the thread for this stop reply packet
lldb::tid_t tid;
while (!value.empty()) {
llvm::StringRef tid_str;
@@ -2245,8 +2224,7 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
} else if (key.compare("thread-pcs") == 0) {
m_thread_pcs.clear();
// A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
+ // process that includes the thread for this stop reply packet
lldb::addr_t pc;
while (!value.empty()) {
llvm::StringRef pc_str;
@@ -2298,13 +2276,10 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
desc_extractor.GetHexByteString(description);
} else if (key.compare("memory") == 0) {
// Expedited memory. GDB servers can choose to send back expedited
- // memory
- // that can populate the L1 memory cache in the process so that things
- // like
- // the frame pointer backchain can be expedited. This will help stack
- // backtracing be more efficient by not having to send as many memory
- // read
- // requests down the remote GDB server.
+ // memory that can populate the L1 memory cache in the process so that
+ // things like the frame pointer backchain can be expedited. This will
+ // help stack backtracing be more efficient by not having to send as
+ // many memory read requests down the remote GDB server.
// Key/value pair format: memory:<addr>=<bytes>;
// <addr> is a number whose base will be interpreted by the prefix:
@@ -2356,7 +2331,8 @@ StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
if (tid == LLDB_INVALID_THREAD_ID) {
// A thread id may be invalid if the response is old style 'S' packet
// which does not provide the
- // thread information. So update the thread list and choose the first one.
+ // thread information. So update the thread list and choose the first
+ // one.
UpdateThreadIDList();
if (!m_thread_ids.empty()) {
@@ -2389,9 +2365,9 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_thread_ids.clear();
m_thread_pcs.clear();
- // Set the thread stop info. It might have a "threads" key whose value is
- // a list of all thread IDs in the current process, so m_thread_ids might
- // get set.
+ // Set the thread stop info. It might have a "threads" key whose value is a
+ // list of all thread IDs in the current process, so m_thread_ids might get
+ // set.
// Scope for the lock
{
@@ -2422,8 +2398,8 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_initial_tid = LLDB_INVALID_THREAD_ID;
}
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
m_thread_list_real.RefreshStateAfterStop();
}
@@ -2431,8 +2407,8 @@ Status ProcessGDBRemote::DoHalt(bool &caused_stop) {
Status error;
if (m_public_state.GetValue() == eStateAttaching) {
- // We are being asked to halt during an attach. We need to just close
- // our file handle and debugserver will go away, and we can be done...
+ // We are being asked to halt during an attach. We need to just close our
+ // file handle and debugserver will go away, and we can be done...
m_gdb_comm.Disconnect();
} else
caused_stop = m_gdb_comm.Interrupt();
@@ -2475,31 +2451,24 @@ Status ProcessGDBRemote::DoDestroy() {
log->Printf("ProcessGDBRemote::DoDestroy()");
// There is a bug in older iOS debugservers where they don't shut down the
- // process
- // they are debugging properly. If the process is sitting at a breakpoint or
- // an exception,
- // this can cause problems with restarting. So we check to see if any of our
- // threads are stopped
- // at a breakpoint, and if so we remove all the breakpoints, resume the
- // process, and THEN
- // destroy it again.
+ // process they are debugging properly. If the process is sitting at a
+ // breakpoint or an exception, this can cause problems with restarting. So
+ // we check to see if any of our threads are stopped at a breakpoint, and if
+ // so we remove all the breakpoints, resume the process, and THEN destroy it
+ // again.
//
// Note, we don't have a good way to test the version of debugserver, but I
- // happen to know that
- // the set of all the iOS debugservers which don't support
- // GetThreadSuffixSupported() and that of
- // the debugservers with this bug are equal. There really should be a better
- // way to test this!
+ // happen to know that the set of all the iOS debugservers which don't
+ // support GetThreadSuffixSupported() and that of the debugservers with this
+ // bug are equal. There really should be a better way to test this!
//
// We also use m_destroy_tried_resuming to make sure we only do this once, if
- // we resume and then halt and
- // get called here to destroy again and we're still at a breakpoint or
- // exception, then we should
- // just do the straight-forward kill.
+ // we resume and then halt and get called here to destroy again and we're
+ // still at a breakpoint or exception, then we should just do the straight-
+ // forward kill.
//
// And of course, if we weren't able to stop the process by the time we get
- // here, it isn't
- // necessary (or helpful) to do any of this.
+ // here, it isn't necessary (or helpful) to do any of this.
if (!m_gdb_comm.GetThreadSuffixSupported() &&
m_public_state.GetValue() != eStateRunning) {
@@ -2514,9 +2483,8 @@ Status ProcessGDBRemote::DoDestroy() {
"destroy once already, not doing it again.");
} else {
// At present, the plans are discarded and the breakpoints disabled
- // Process::Destroy,
- // but we really need it to happen here and it doesn't matter if we do
- // it twice.
+ // Process::Destroy, but we really need it to happen here and it
+ // doesn't matter if we do it twice.
m_thread_list.DiscardThreadPlans();
DisableAllBreakpointSites();
@@ -2553,12 +2521,11 @@ Status ProcessGDBRemote::DoDestroy() {
m_destroy_tried_resuming = true;
// If we are going to run again before killing, it would be good to
- // suspend all the threads
- // before resuming so they won't get into more trouble. Sadly, for
- // the threads stopped with
- // the breakpoint or exception, the exception doesn't get cleared if
- // it is suspended, so we do
- // have to run the risk of letting those threads proceed a bit.
+ // suspend all the threads before resuming so they won't get into
+ // more trouble. Sadly, for the threads stopped with the breakpoint
+ // or exception, the exception doesn't get cleared if it is
+ // suspended, so we do have to run the risk of letting those threads
+ // proceed a bit.
{
std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
@@ -2605,17 +2572,14 @@ Status ProcessGDBRemote::DoDestroy() {
if (packet_cmd == 'W' || packet_cmd == 'X') {
#if defined(__APPLE__)
// For Native processes on Mac OS X, we launch through the Host
- // Platform, then hand the process off
- // to debugserver, which becomes the parent process through
- // "PT_ATTACH". Then when we go to kill
- // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we
- // call waitpid which returns
- // with no error and the correct status. But amusingly enough that
- // doesn't seem to actually reap
+ // Platform, then hand the process off to debugserver, which becomes
+ // the parent process through "PT_ATTACH". Then when we go to kill
+ // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then
+ // we call waitpid which returns with no error and the correct
+ // status. But amusingly enough that doesn't seem to actually reap
// the process, but instead it is left around as a Zombie. Probably
- // the kernel is in the process of
- // switching ownership back to lldb which was the original parent, and
- // gets confused in the handoff.
+ // the kernel is in the process of switching ownership back to lldb
+ // which was the original parent, and gets confused in the handoff.
// Anyway, so call waitpid here to finally reap it.
PlatformSP platform_sp(GetTarget().GetPlatform());
if (platform_sp && platform_sp->IsHost()) {
@@ -2687,9 +2651,8 @@ void ProcessGDBRemote::SetLastStopPacket(
if (GetTarget().GetNonStopModeEnabled() == false)
m_stop_packet_stack.clear();
- // Add this stop packet to the stop packet stack
- // This stack will get popped and examined when we switch to the
- // Stopped state
+ // Add this stop packet to the stop packet stack This stack will get popped
+ // and examined when we switch to the Stopped state
m_stop_packet_stack.push_back(response);
}
}
@@ -2721,12 +2684,11 @@ addr_t ProcessGDBRemote::GetImageInfoAddress() {
}
void ProcessGDBRemote::WillPublicStop() {
- // See if the GDB remote client supports the JSON threads info.
- // If so, we gather stop info for all threads, expedited registers,
- // expedited memory, runtime queue information (iOS and MacOSX only),
- // and more. Expediting memory will help stack backtracing be much
- // faster. Expediting registers will make sure we don't have to read
- // the thread registers for GPRs.
+ // See if the GDB remote client supports the JSON threads info. If so, we
+ // gather stop info for all threads, expedited registers, expedited memory,
+ // runtime queue information (iOS and MacOSX only), and more. Expediting
+ // memory will help stack backtracing be much faster. Expediting registers
+ // will make sure we don't have to read the thread registers for GPRs.
m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
if (m_jthreadsinfo_sp) {
@@ -2776,14 +2738,13 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
error.Clear();
if (binary_memory_read) {
// The lower level GDBRemoteCommunication packet receive layer has
- // already de-quoted any
- // 0x7d character escaping that was present in the packet
+ // already de-quoted any 0x7d character escaping that was present in
+ // the packet
size_t data_received_size = response.GetBytesLeft();
if (data_received_size > size) {
// Don't write past the end of BUF if the remote debug server gave us
- // too
- // much data for some reason.
+ // too much data for some reason.
data_received_size = size;
}
memcpy(buf, response.GetStringRef().data(), data_received_size);
@@ -2807,6 +2768,145 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
return 0;
}
+Status ProcessGDBRemote::WriteObjectFile(
+ std::vector<ObjectFile::LoadableData> entries) {
+ Status error;
+ // Sort the entries by address because some writes, like those to flash
+ // memory, must happen in order of increasing address.
+ std::stable_sort(
+ std::begin(entries), std::end(entries),
+ [](const ObjectFile::LoadableData a, const ObjectFile::LoadableData b) {
+ return a.Dest < b.Dest;
+ });
+ m_allow_flash_writes = true;
+ error = Process::WriteObjectFile(entries);
+ if (error.Success())
+ error = FlashDone();
+ else
+ // Even though some of the writing failed, try to send a flash done if some
+ // of the writing succeeded so the flash state is reset to normal, but
+ // don't stomp on the error status that was set in the write failure since
+ // that's the one we want to report back.
+ FlashDone();
+ m_allow_flash_writes = false;
+ return error;
+}
+
+bool ProcessGDBRemote::HasErased(FlashRange range) {
+ auto size = m_erased_flash_ranges.GetSize();
+ for (size_t i = 0; i < size; ++i)
+ if (m_erased_flash_ranges.GetEntryAtIndex(i)->Contains(range))
+ return true;
+ return false;
+}
+
+Status ProcessGDBRemote::FlashErase(lldb::addr_t addr, size_t size) {
+ Status status;
+
+ MemoryRegionInfo region;
+ status = GetMemoryRegionInfo(addr, region);
+ if (!status.Success())
+ return status;
+
+ // The gdb spec doesn't say if erasures are allowed across multiple regions,
+ // but we'll disallow it to be safe and to keep the logic simple by worring
+ // about only one region's block size. DoMemoryWrite is this function's
+ // primary user, and it can easily keep writes within a single memory region
+ if (addr + size > region.GetRange().GetRangeEnd()) {
+ status.SetErrorString("Unable to erase flash in multiple regions");
+ return status;
+ }
+
+ uint64_t blocksize = region.GetBlocksize();
+ if (blocksize == 0) {
+ status.SetErrorString("Unable to erase flash because blocksize is 0");
+ return status;
+ }
+
+ // Erasures can only be done on block boundary adresses, so round down addr
+ // and round up size
+ lldb::addr_t block_start_addr = addr - (addr % blocksize);
+ size += (addr - block_start_addr);
+ if ((size % blocksize) != 0)
+ size += (blocksize - size % blocksize);
+
+ FlashRange range(block_start_addr, size);
+
+ if (HasErased(range))
+ return status;
+
+ // We haven't erased the entire range, but we may have erased part of it.
+ // (e.g., block A is already erased and range starts in A and ends in B). So,
+ // adjust range if necessary to exclude already erased blocks.
+ if (!m_erased_flash_ranges.IsEmpty()) {
+ // Assuming that writes and erasures are done in increasing addr order,
+ // because that is a requirement of the vFlashWrite command. Therefore, we
+ // only need to look at the last range in the list for overlap.
+ const auto &last_range = *m_erased_flash_ranges.Back();
+ if (range.GetRangeBase() < last_range.GetRangeEnd()) {
+ auto overlap = last_range.GetRangeEnd() - range.GetRangeBase();
+ // overlap will be less than range.GetByteSize() or else HasErased()
+ // would have been true
+ range.SetByteSize(range.GetByteSize() - overlap);
+ range.SetRangeBase(range.GetRangeBase() + overlap);
+ }
+ }
+
+ StreamString packet;
+ packet.Printf("vFlashErase:%" PRIx64 ",%" PRIx64, range.GetRangeBase(),
+ (uint64_t)range.GetByteSize());
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_erased_flash_ranges.Insert(range, true);
+ } else {
+ if (response.IsErrorResponse())
+ status.SetErrorStringWithFormat("flash erase failed for 0x%" PRIx64,
+ addr);
+ else if (response.IsUnsupportedResponse())
+ status.SetErrorStringWithFormat("GDB server does not support flashing");
+ else
+ status.SetErrorStringWithFormat(
+ "unexpected response to GDB server flash erase packet '%s': '%s'",
+ packet.GetData(), response.GetStringRef().c_str());
+ }
+ } else {
+ status.SetErrorStringWithFormat("failed to send packet: '%s'",
+ packet.GetData());
+ }
+ return status;
+}
+
+Status ProcessGDBRemote::FlashDone() {
+ Status status;
+ // If we haven't erased any blocks, then we must not have written anything
+ // either, so there is no need to actually send a vFlashDone command
+ if (m_erased_flash_ranges.IsEmpty())
+ return status;
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse("vFlashDone", response, true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_erased_flash_ranges.Clear();
+ } else {
+ if (response.IsErrorResponse())
+ status.SetErrorStringWithFormat("flash done failed");
+ else if (response.IsUnsupportedResponse())
+ status.SetErrorStringWithFormat("GDB server does not support flashing");
+ else
+ status.SetErrorStringWithFormat(
+ "unexpected response to GDB server flash done packet: '%s'",
+ response.GetStringRef().c_str());
+ }
+ } else {
+ status.SetErrorStringWithFormat("failed to send flash done packet");
+ }
+ return status;
+}
+
size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
size_t size, Status &error) {
GetMaxMemorySize();
@@ -2819,10 +2919,33 @@ size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
size = max_memory_size;
}
- StreamString packet;
- packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
- packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
+ StreamGDBRemote packet;
+
+ MemoryRegionInfo region;
+ Status region_status = GetMemoryRegionInfo(addr, region);
+
+ bool is_flash =
+ region_status.Success() && region.GetFlash() == MemoryRegionInfo::eYes;
+
+ if (is_flash) {
+ if (!m_allow_flash_writes) {
+ error.SetErrorString("Writing to flash memory is not allowed");
+ return 0;
+ }
+ // Keep the write within a flash memory region
+ if (addr + size > region.GetRange().GetRangeEnd())
+ size = region.GetRange().GetRangeEnd() - addr;
+ // Flash memory must be erased before it can be written
+ error = FlashErase(addr, size);
+ if (!error.Success())
+ return 0;
+ packet.Printf("vFlashWrite:%" PRIx64 ":", addr);
+ packet.PutEscapedBytes(buf, size);
+ } else {
+ packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
+ packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ }
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
true) ==
@@ -2918,8 +3041,8 @@ Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) {
switch (supported) {
case eLazyBoolCalculate:
- // We should never be deallocating memory without allocating memory
- // first so we should never get eLazyBoolCalculate
+ // We should never be deallocating memory without allocating memory first
+ // so we should never get eLazyBoolCalculate
error.SetErrorString(
"tried to deallocate memory without ever allocating memory");
break;
@@ -2991,18 +3114,14 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
// SupportsGDBStoppointPacket() simply checks a boolean, indicating if this
- // breakpoint type
- // is supported by the remote stub. These are set to true by default, and
- // later set to false
- // only after we receive an unimplemented response when sending a breakpoint
- // packet. This means
- // initially that unless we were specifically instructed to use a hardware
- // breakpoint, LLDB will
- // attempt to set a software breakpoint. HardwareRequired() also queries a
- // boolean variable which
- // indicates if the user specifically asked for hardware breakpoints. If true
- // then we will
- // skip over software breakpoints.
+ // breakpoint type is supported by the remote stub. These are set to true by
+ // default, and later set to false only after we receive an unimplemented
+ // response when sending a breakpoint packet. This means initially that
+ // unless we were specifically instructed to use a hardware breakpoint, LLDB
+ // will attempt to set a software breakpoint. HardwareRequired() also queries
+ // a boolean variable which indicates if the user specifically asked for
+ // hardware breakpoints. If true then we will skip over software
+ // breakpoints.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) &&
(!bp_site->HardwareRequired())) {
// Try to send off a software breakpoint packet ($Z0)
@@ -3015,19 +3134,14 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
return error;
}
- // SendGDBStoppointTypePacket() will return an error if it was unable to set
- // this
- // breakpoint. We need to differentiate between a error specific to placing
- // this breakpoint
- // or if we have learned that this breakpoint type is unsupported. To do
- // this, we
- // must test the support boolean for this breakpoint type to see if it now
- // indicates that
- // this breakpoint type is unsupported. If they are still supported then we
- // should return
+ // SendGDBStoppointTypePacket() will return an error if it was unable to
+ // set this breakpoint. We need to differentiate between a error specific
+ // to placing this breakpoint or if we have learned that this breakpoint
+ // type is unsupported. To do this, we must test the support boolean for
+ // this breakpoint type to see if it now indicates that this breakpoint
+ // type is unsupported. If they are still supported then we should return
// with the error code. If they are now unsupported, then we would like to
- // fall through
- // and try another form of breakpoint.
+ // fall through and try another form of breakpoint.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) {
if (error_no != UINT8_MAX)
error.SetErrorStringWithFormat(
@@ -3038,21 +3152,18 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
}
// We reach here when software breakpoints have been found to be
- // unsupported. For future
- // calls to set a breakpoint, we will not attempt to set a breakpoint with a
- // type that is
- // known not to be supported.
+ // unsupported. For future calls to set a breakpoint, we will not attempt
+ // to set a breakpoint with a type that is known not to be supported.
if (log)
log->Printf("Software breakpoints are unsupported");
// So we will fall through and try a hardware breakpoint
}
- // The process of setting a hardware breakpoint is much the same as above. We
- // check the
- // supported boolean for this breakpoint type, and if it is thought to be
- // supported then we
- // will try to set this breakpoint with a hardware breakpoint.
+ // The process of setting a hardware breakpoint is much the same as above.
+ // We check the supported boolean for this breakpoint type, and if it is
+ // thought to be supported then we will try to set this breakpoint with a
+ // hardware breakpoint.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
// Try to send off a hardware breakpoint packet ($Z1)
uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
@@ -3094,8 +3205,8 @@ Status ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
return error;
}
- // As a last resort we want to place a manual breakpoint. An instruction
- // is placed into the process memory using memory write packets.
+ // As a last resort we want to place a manual breakpoint. An instruction is
+ // placed into the process memory using memory write packets.
return EnableSoftwareBreakpoint(bp_site);
}
@@ -3225,10 +3336,9 @@ Status ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) {
log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
watchID, (uint64_t)addr);
- // See also 'class WatchpointSentry' within StopInfo.cpp.
- // This disabling attempt might come from the user-supplied actions, we'll
- // route it in order for
- // the watchpoint object to intelligently process this action.
+ // See also 'class WatchpointSentry' within StopInfo.cpp. This disabling
+ // attempt might come from the user-supplied actions, we'll route it in
+ // order for the watchpoint object to intelligently process this action.
wp->SetEnabled(false, notify);
return error;
}
@@ -3313,8 +3423,8 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
static FileSpec g_debugserver_file_spec;
ProcessLaunchInfo debugserver_launch_info;
- // Make debugserver run in its own session so signals generated by
- // special terminal key sequences (^C) don't affect debugserver.
+ // Make debugserver run in its own session so signals generated by special
+ // terminal key sequences (^C) don't affect debugserver.
debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
const std::weak_ptr<ProcessGDBRemote> this_wp =
@@ -3325,27 +3435,22 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
int communication_fd = -1;
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Auto close the sockets we might open up unless everything goes OK. This
- // helps us not leak file descriptors when things go wrong.
- lldb_utility::CleanUp<int, int> our_socket(-1, -1, close);
- lldb_utility::CleanUp<int, int> gdb_socket(-1, -1, close);
-
// Use a socketpair on non-Windows systems for security and performance
// reasons.
- {
- int sockets[2]; /* the pair of socket descriptors */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
- error.SetErrorToErrno();
- return error;
- }
-
- our_socket.set(sockets[0]);
- gdb_socket.set(sockets[1]);
+ int sockets[2]; /* the pair of socket descriptors */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
+ error.SetErrorToErrno();
+ return error;
}
+ int our_socket = sockets[0];
+ int gdb_socket = sockets[1];
+ CleanUp cleanup_our(close, our_socket);
+ CleanUp cleanup_gdb(close, gdb_socket);
+
// Don't let any child processes inherit our communication socket
- SetCloexecFlag(our_socket.get());
- communication_fd = gdb_socket.get();
+ SetCloexecFlag(our_socket);
+ communication_fd = gdb_socket;
#endif
error = m_gdb_comm.StartDebugserverProcess(
@@ -3359,10 +3464,10 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
- // Our process spawned correctly, we can now set our connection to use our
- // end of the socket pair
- m_gdb_comm.SetConnection(
- new ConnectionFileDescriptor(our_socket.release(), true));
+ // Our process spawned correctly, we can now set our connection to use
+ // our end of the socket pair
+ cleanup_our.disable();
+ m_gdb_comm.SetConnection(new ConnectionFileDescriptor(our_socket, true));
#endif
StartAsyncThread();
}
@@ -3377,9 +3482,9 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver(
}
if (m_gdb_comm.IsConnected()) {
- // Finish the connection process by doing the handshake without connecting
- // (send NULL URL)
- ConnectToDebugserver("");
+ // Finish the connection process by doing the handshake without
+ // connecting (send NULL URL)
+ error = ConnectToDebugserver("");
} else {
error.SetErrorString("connection failed");
}
@@ -3393,8 +3498,8 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
int signo, // Zero for no signal
int exit_status // Exit value of process if signal is zero
) {
- // "debugserver_pid" argument passed in is the process ID for
- // debugserver that we are tracking...
+ // "debugserver_pid" argument passed in is the process ID for debugserver
+ // that we are tracking...
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
const bool handled = true;
@@ -3410,12 +3515,12 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
return handled;
- // Sleep for a half a second to make sure our inferior process has
- // time to set its exit status before we set it incorrectly when
- // both the debugserver and the inferior process shut down.
+ // Sleep for a half a second to make sure our inferior process has time to
+ // set its exit status before we set it incorrectly when both the debugserver
+ // and the inferior process shut down.
usleep(500000);
- // If our process hasn't yet exited, debugserver might have died.
- // If the process did exit, then we are reaping it.
+ // If our process hasn't yet exited, debugserver might have died. If the
+ // process did exit, then we are reaping it.
const StateType state = process_sp->GetState();
if (state != eStateInvalid && state != eStateUnloaded &&
@@ -3438,8 +3543,8 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
process_sp->SetExitStatus(-1, error_str);
}
- // Debugserver has exited we need to let our ProcessGDBRemote
- // know that it no longer has a debugserver instance
+ // Debugserver has exited we need to let our ProcessGDBRemote know that it no
+ // longer has a debugserver instance
process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
return handled;
}
@@ -3529,10 +3634,9 @@ bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) {
// check for more stop reasons
HandleStopReplySequence();
- // if the process is stopped then we need to fake a resume
- // so that we can stop properly with the new break. This
- // is possible due to SetPrivateState() broadcasting the
- // state change as a side effect.
+ // if the process is stopped then we need to fake a resume so that we can
+ // stop properly with the new break. This is possible due to
+ // SetPrivateState() broadcasting the state change as a side effect.
if (GetPrivateState() == lldb::StateType::eStateStopped) {
SetPrivateState(lldb::StateType::eStateRunning);
}
@@ -3605,12 +3709,11 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
response);
// We need to immediately clear the thread ID list so we are sure
- // to get a valid list of threads.
- // The thread ID list might be contained within the "response", or
- // the stop reply packet that
+ // to get a valid list of threads. The thread ID list might be
+ // contained within the "response", or the stop reply packet that
// caused the stop. So clear it now before we give the stop reply
- // packet to the process
- // using the process->SetLastStopPacket()...
+ // packet to the process using the
+ // process->SetLastStopPacket()...
process->ClearThreadIDList();
switch (stop_state) {
@@ -3647,17 +3750,14 @@ thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
// Check to see if we were trying to attach and if we got back
// the "E87" error code from debugserver -- this indicates that
// the process is not debuggable. Return a slightly more
- // helpful
- // error message about why the attach failed.
+ // helpful error message about why the attach failed.
if (::strstr(continue_cstr, "vAttach") != NULL &&
response.GetError() == 0x87) {
process->SetExitStatus(-1, "cannot attach to process due to "
"System Integrity Protection");
- }
- // E01 code from vAttach means that the attach failed
- if (::strstr(continue_cstr, "vAttach") != NULL &&
- response.GetError() == 0x1) {
- process->SetExitStatus(-1, "unable to attach");
+ } else if (::strstr(continue_cstr, "vAttach") != NULL &&
+ response.GetStatus().Fail()) {
+ process->SetExitStatus(-1, response.GetStatus().AsCString());
} else {
process->SetExitStatus(-1, "lost connection");
}
@@ -3769,8 +3869,8 @@ Status ProcessGDBRemote::UpdateAutomaticSignalFiltering() {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
LLDB_LOG(log, "Check if need to update ignored signals");
- // QPassSignals package is not supported by the server,
- // there is no way we can ignore any signals on server side.
+ // QPassSignals package is not supported by the server, there is no way we
+ // can ignore any signals on server side.
if (!m_gdb_comm.GetQPassSignalsSupported())
return Status();
@@ -3894,9 +3994,9 @@ ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) {
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -3966,9 +4066,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender(
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -3999,9 +4099,9 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() {
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
+ // these characters in its packet output -- so we add the quoted version of
+ // the } character here manually in case we talk to a debugserver which un-
+ // escapes the characters at packet read time.
packet << (char)(0x7d ^ 0x20);
StringExtractorGDBRemote response;
@@ -4026,14 +4126,14 @@ Status ProcessGDBRemote::ConfigureStructuredData(
return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp);
}
-// Establish the largest memory read/write payloads we should use.
-// If the remote stub has a max packet size, stay under that size.
+// Establish the largest memory read/write payloads we should use. If the
+// remote stub has a max packet size, stay under that size.
//
-// If the remote stub's max packet size is crazy large, use a
-// reasonable largeish default.
+// If the remote stub's max packet size is crazy large, use a reasonable
+// largeish default.
//
-// If the remote stub doesn't advertise a max packet size, use a
-// conservative default.
+// If the remote stub doesn't advertise a max packet size, use a conservative
+// default.
void ProcessGDBRemote::GetMaxMemorySize() {
const uint64_t reasonable_largeish_default = 128 * 1024;
@@ -4045,15 +4145,15 @@ void ProcessGDBRemote::GetMaxMemorySize() {
// Save the stub's claimed maximum packet size
m_remote_stub_max_memory_size = stub_max_size;
- // Even if the stub says it can support ginormous packets,
- // don't exceed our reasonable largeish default packet size.
+ // Even if the stub says it can support ginormous packets, don't exceed
+ // our reasonable largeish default packet size.
if (stub_max_size > reasonable_largeish_default) {
stub_max_size = reasonable_largeish_default;
}
- // Memory packet have other overheads too like Maddr,size:#NN
- // Instead of calculating the bytes taken by size and addr every
- // time, we take a maximum guess here.
+ // Memory packet have other overheads too like Maddr,size:#NN Instead of
+ // calculating the bytes taken by size and addr every time, we take a
+ // maximum guess here.
if (stub_max_size > 70)
stub_max_size -= 32 + 32 + 6;
else {
@@ -4140,13 +4240,8 @@ void ProcessGDBRemote::PrefetchModuleSpecs(
}
}
-bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) {
- if (m_gdb_comm.GetOSVersion(major, minor, update))
- return true;
- // We failed to get the host OS version, defer to the base
- // implementation to correctly invalidate the arguments.
- return Process::GetHostOSVersion(major, minor, update);
+llvm::VersionTuple ProcessGDBRemote::GetHostOSVersion() {
+ return m_gdb_comm.GetOSVersion();
}
namespace {
@@ -4237,7 +4332,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
} else if (name == "format") {
format_set = true;
Format format = eFormatInvalid;
- if (Args::StringToFormat(value.data(), format, NULL).Success())
+ if (OptionArgParser::ToFormat(value.data(), format, NULL).Success())
reg_info.format = format;
else if (value == "vector-sint8")
reg_info.format = eFormatVectorOfSInt8;
@@ -4311,8 +4406,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
}
// Only update the register set name if we didn't get a "reg_set"
+ // attribute. "set_name" will be empty if we didn't have a "reg_set"
// attribute.
- // "set_name" will be empty if we didn't have a "reg_set" attribute.
if (!set_name && !gdb_group.empty())
set_name.SetCString(gdb_group.c_str());
@@ -4339,8 +4434,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
} // namespace {}
-// query the target of gdb-remote for extended target information
-// return: 'true' on success
+// query the target of gdb-remote for extended target information return:
+// 'true' on success
// 'false' on failure
bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
// Make sure LLDB has an XML parser it can use first
@@ -4409,15 +4504,27 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
return true; // Keep iterating through all children of the target_node
});
+ // If the target.xml includes an architecture entry like
+ // <architecture>i386:x86-64</architecture> (seen from VMWare ESXi)
+ // <architecture>arm</architecture> (seen from Segger JLink on unspecified arm board)
+ // use that if we don't have anything better.
+ if (!arch_to_use.IsValid() && !target_info.arch.empty()) {
+ if (target_info.arch == "i386:x86-64")
+ {
+ // We don't have any information about vendor or OS.
+ arch_to_use.SetTriple("x86_64--");
+ GetTarget().MergeArchitecture(arch_to_use);
+ }
+ }
+
// Initialize these outside of ParseRegisters, since they should not be
// reset inside each include feature
uint32_t cur_reg_num = 0;
uint32_t reg_offset = 0;
- // Don't use Process::GetABI, this code gets called from DidAttach, and in
- // that context we haven't
- // set the Target's architecture yet, so the ABI is also potentially
- // incorrect.
+ // Don't use Process::GetABI, this code gets called from DidAttach, and
+ // in that context we haven't set the Target's architecture yet, so the
+ // ABI is also potentially incorrect.
ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use);
for (auto &feature_node : feature_nodes) {
ParseRegisters(feature_node, target_info, this->m_register_info,
@@ -4758,8 +4865,8 @@ void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) {
// do anything
Process::ModulesDidLoad(module_list);
- // After loading shared libraries, we can ask our remote GDB server if
- // it needs any symbols.
+ // After loading shared libraries, we can ask our remote GDB server if it
+ // needs any symbols.
m_gdb_comm.ServeSymbolLookups(this);
}
@@ -4817,8 +4924,8 @@ std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
has_used_usec = true;
usec_value.getAsInteger(0, curr_used_usec);
} else {
- // We didn't find what we want, it is probably
- // an older version. Bail out.
+ // We didn't find what we want, it is probably an older version. Bail
+ // out.
profileDataExtractor.SetFilePos(input_file_pos);
}
}
@@ -4840,8 +4947,8 @@ std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id)));
if (good_first_time || good_subsequent_time) {
- // We try to avoid doing too many index id reservation,
- // resulting in fast increase of index ids.
+ // We try to avoid doing too many index id reservation, resulting in
+ // fast increase of index ids.
output_stream << name << ":";
int32_t index_id = AssignIndexIDToThread(thread_id);
@@ -4892,7 +4999,7 @@ ParseStructuredDataPacket(llvm::StringRef packet) {
if (!packet.consume_front(s_async_json_packet_prefix)) {
if (log) {
log->Printf(
- "GDBRemoteCommmunicationClientBase::%s() received $J packet "
+ "GDBRemoteCommunicationClientBase::%s() received $J packet "
"but was not a StructuredData packet: packet starts with "
"%s",
__FUNCTION__,
@@ -4901,8 +5008,7 @@ ParseStructuredDataPacket(llvm::StringRef packet) {
return StructuredData::ObjectSP();
}
- // This is an asynchronous JSON packet, destined for a
- // StructuredDataPlugin.
+ // This is an asynchronous JSON packet, destined for a StructuredDataPlugin.
StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet);
if (log) {
if (json_sp) {
@@ -5137,8 +5243,9 @@ public:
~CommandObjectProcessGDBRemotePacketMonitor() {}
- bool DoExecute(const char *command, CommandReturnObject &result) override {
- if (command == NULL || command[0] == '\0') {
+ bool DoExecute(llvm::StringRef command,
+ CommandReturnObject &result) override {
+ if (command.empty()) {
result.AppendErrorWithFormat("'%s' takes a command string argument",
m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
@@ -5150,14 +5257,15 @@ public:
if (process) {
StreamString packet;
packet.PutCString("qRcmd,");
- packet.PutBytesAsRawHex8(command, strlen(command));
+ packet.PutBytesAsRawHex8(command.data(), command.size());
bool send_async = true;
StringExtractorGDBRemote response;
- process->GetGDBRemote().SendPacketAndWaitForResponse(
- packet.GetString(), response, send_async);
- result.SetStatus(eReturnStatusSuccessFinishResult);
Stream &output_strm = result.GetOutputStream();
+ process->GetGDBRemote().SendPacketAndReceiveResponseWithOutputSupport(
+ packet.GetString(), response, send_async,
+ [&output_strm](llvm::StringRef output) { output_strm << output; });
+ result.SetStatus(eReturnStatusSuccessFinishResult);
output_strm.Printf(" packet: %s\n", packet.GetData());
const std::string &response_str = response.GetStringRef();
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 42d1c4ecd666..45bb2d4c28e7 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -144,6 +144,9 @@ public:
size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) override;
+ Status
+ WriteObjectFile(std::vector<ObjectFile::LoadableData> entries) override;
+
size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size,
Status &error) override;
@@ -214,8 +217,7 @@ public:
void PrefetchModuleSpecs(llvm::ArrayRef<FileSpec> module_file_specs,
const llvm::Triple &triple) override;
- bool GetHostOSVersion(uint32_t &major, uint32_t &minor,
- uint32_t &update) override;
+ llvm::VersionTuple GetHostOSVersion() override;
size_t LoadModules(LoadedModuleInfoList &module_list) override;
@@ -302,6 +304,11 @@ protected:
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ bool m_allow_flash_writes;
+ using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>;
+ using FlashRange = FlashRangeVector::Entry;
+ FlashRangeVector m_erased_flash_ranges;
+
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
@@ -408,6 +415,12 @@ protected:
Status UpdateAutomaticSignalFiltering() override;
+ Status FlashErase(lldb::addr_t addr, size_t size);
+
+ Status FlashDone();
+
+ bool HasErased(FlashRange range);
+
private:
//------------------------------------------------------------------
// For ProcessGDBRemote only
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 27dd03bfc7bc..a525c16b9f13 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -24,7 +24,7 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -55,7 +55,7 @@ ThreadGDBRemote::~ThreadGDBRemote() {
const char *ThreadGDBRemote::GetName() {
if (m_thread_name.empty())
- return NULL;
+ return nullptr;
return m_thread_name.c_str();
}
@@ -80,10 +80,9 @@ void ThreadGDBRemote::SetQueueInfo(std::string &&queue_name,
const char *ThreadGDBRemote::GetQueueName() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid()) {
if (m_dispatch_queue_name.empty())
return nullptr;
@@ -110,15 +109,14 @@ const char *ThreadGDBRemote::GetQueueName() {
return m_dispatch_queue_name.c_str();
}
}
- return NULL;
+ return nullptr;
}
QueueKind ThreadGDBRemote::GetQueueKind() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid()) {
return m_queue_kind;
}
@@ -141,10 +139,9 @@ QueueKind ThreadGDBRemote::GetQueueKind() {
queue_id_t ThreadGDBRemote::GetQueueID() {
// If our cached queue info is valid, then someone called
- // ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this
- // case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
+ // ThreadGDBRemote::SetQueueInfo(...) with valid information that was gleaned
+ // from the stop reply packet. In this case we trust that the info is valid
+ // in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid())
return m_queue_serial_number;
@@ -275,11 +272,11 @@ void ThreadGDBRemote::RefreshStateAfterStop() {
// Invalidate all registers in our register context. We don't set "force" to
// true because the stop reply packet might have had some register values
// that were expedited and these will already be copied into the register
- // context by the time this function gets called. The GDBRemoteRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
+ // context by the time this function gets called. The
+ // GDBRemoteRegisterContext class has been made smart enough to detect when
+ // it needs to invalidate which registers are valid by putting hooks in the
+ // register read and register supply functions where they check the process
+ // stop ID and do the right thing.
const bool force = false;
GetRegisterContext()->InvalidateIfNeeded(force);
}
@@ -292,8 +289,8 @@ void ThreadGDBRemote::Dump(Log *log, uint32_t index) {}
bool ThreadGDBRemote::ShouldStop(bool &step_more) { return true; }
lldb::RegisterContextSP ThreadGDBRemote::GetRegisterContext() {
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
return m_reg_context_sp;
}
@@ -310,7 +307,8 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
if (process_sp) {
ProcessGDBRemote *gdb_process =
static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not supported.
+ // read_all_registers_at_once will be true if 'p' packet is not
+ // supported.
bool read_all_registers_at_once =
!gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
reg_ctx_sp.reset(new GDBRemoteRegisterContext(
@@ -319,7 +317,7 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
}
} else {
Unwind *unwinder = GetUnwinder();
- if (unwinder)
+ if (unwinder != nullptr)
reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
diff --git a/source/Plugins/Process/mach-core/CMakeLists.txt b/source/Plugins/Process/mach-core/CMakeLists.txt
index 18f6ff581ea3..e79cd82c92a6 100644
--- a/source/Plugins/Process/mach-core/CMakeLists.txt
+++ b/source/Plugins/Process/mach-core/CMakeLists.txt
@@ -1,5 +1,3 @@
-include_directories(../Utility)
-
add_lldb_library(lldbPluginProcessMachCore PLUGIN
ProcessMachCore.cpp
ThreadMachCore.cpp
diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/source/Plugins/Process/mach-core/ProcessMachCore.cpp
index d21651b77ee0..bfa35ed506a9 100644
--- a/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -35,7 +35,7 @@
// Project includes
#include "ProcessMachCore.h"
-#include "StopInfoMachException.h"
+#include "Plugins/Process/Utility/StopInfoMachException.h"
#include "ThreadMachCore.h"
// Needed for the plug-in names for the dynamic loaders.
@@ -91,11 +91,10 @@ bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,
// For now we are just making sure the file exists for a given module
if (!m_core_module_sp && m_core_file.Exists()) {
- // Don't add the Target's architecture to the ModuleSpec - we may be working
- // with a core file that doesn't have the correct cpusubtype in the header
- // but we should still try to use it -
- // ModuleSpecList::FindMatchingModuleSpec
- // enforces a strict arch mach.
+ // Don't add the Target's architecture to the ModuleSpec - we may be
+ // working with a core file that doesn't have the correct cpusubtype in the
+ // header but we should still try to use it -
+ // ModuleSpecList::FindMatchingModuleSpec enforces a strict arch mach.
ModuleSpec core_module_spec(m_core_file);
Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
NULL, NULL, NULL));
@@ -125,10 +124,10 @@ ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp,
//----------------------------------------------------------------------
ProcessMachCore::~ProcessMachCore() {
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
}
@@ -162,11 +161,10 @@ bool ProcessMachCore::GetDynamicLoaderAddress(lldb::addr_t addr) {
// header.magic, header.filetype);
if (header.magic == llvm::MachO::MH_MAGIC ||
header.magic == llvm::MachO::MH_MAGIC_64) {
- // Check MH_EXECUTABLE to see if we can find the mach image
- // that contains the shared library list. The dynamic loader
- // (dyld) is what contains the list for user applications,
- // and the mach kernel contains a global that has the list
- // of kexts to load
+ // Check MH_EXECUTABLE to see if we can find the mach image that contains
+ // the shared library list. The dynamic loader (dyld) is what contains the
+ // list for user applications, and the mach kernel contains a global that
+ // has the list of kexts to load
switch (header.filetype) {
case llvm::MachO::MH_DYLINKER:
// printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr);
@@ -272,13 +270,10 @@ Status ProcessMachCore::DoLoadCore() {
} else {
m_core_aranges.Append(range_entry);
}
- // Some core files don't fill in the permissions correctly. If that is the
- // case
- // assume read + execute so clients don't think the memory is not
- // readable,
- // or executable. The memory isn't writable since this plug-in doesn't
- // implement
- // DoWriteMemory.
+ // Some core files don't fill in the permissions correctly. If that is
+ // the case assume read + execute so clients don't think the memory is
+ // not readable, or executable. The memory isn't writable since this
+ // plug-in doesn't implement DoWriteMemory.
uint32_t permissions = section->GetPermissions();
if (permissions == 0)
permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
@@ -309,8 +304,8 @@ Status ProcessMachCore::DoLoadCore() {
}
// This checks for the presence of an LC_IDENT string in a core file;
- // LC_IDENT is very obsolete and should not be used in new code, but
- // if the load command is present, let's use the contents.
+ // LC_IDENT is very obsolete and should not be used in new code, but if the
+ // load command is present, let's use the contents.
std::string corefile_identifier = core_objfile->GetIdentifierString();
if (found_main_binary_definitively == false
&& corefile_identifier.find("Darwin Kernel") != std::string::npos) {
@@ -319,7 +314,7 @@ Status ProcessMachCore::DoLoadCore() {
if (corefile_identifier.find("UUID=") != std::string::npos) {
size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
std::string uuid_str = corefile_identifier.substr(p, 36);
- uuid.SetFromCString(uuid_str.c_str());
+ uuid.SetFromStringRef(uuid_str);
}
if (corefile_identifier.find("stext=") != std::string::npos) {
size_t p = corefile_identifier.find("stext=") + strlen("stext=");
@@ -342,16 +337,12 @@ Status ProcessMachCore::DoLoadCore() {
if (found_main_binary_definitively == false
&& (m_dyld_addr == LLDB_INVALID_ADDRESS
|| m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
- // We need to locate the main executable in the memory ranges
- // we have in the core file. We need to search for both a user-process dyld
- // binary
+ // We need to locate the main executable in the memory ranges we have in
+ // the core file. We need to search for both a user-process dyld binary
// and a kernel binary in memory; we must look at all the pages in the
- // binary so
- // we don't miss one or the other. Step through all memory segments
- // searching for
- // a kernel binary and for a user process dyld -- we'll decide which to
- // prefer
- // later if both are present.
+ // binary so we don't miss one or the other. Step through all memory
+ // segments searching for a kernel binary and for a user process dyld --
+ // we'll decide which to prefer later if both are present.
const size_t num_core_aranges = m_core_aranges.GetSize();
for (size_t i = 0; i < num_core_aranges; ++i) {
@@ -369,13 +360,10 @@ Status ProcessMachCore::DoLoadCore() {
if (found_main_binary_definitively == false
&& m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
// In the case of multiple kernel images found in the core file via
- // exhaustive
- // search, we may not pick the correct one. See if the
- // DynamicLoaderDarwinKernel's
- // search heuristics might identify the correct one.
- // Most of the time, I expect the address from SearchForDarwinKernel() will
- // be the
- // same as the address we found via exhaustive search.
+ // exhaustive search, we may not pick the correct one. See if the
+ // DynamicLoaderDarwinKernel's search heuristics might identify the correct
+ // one. Most of the time, I expect the address from SearchForDarwinKernel()
+ // will be the same as the address we found via exhaustive search.
if (GetTarget().GetArchitecture().IsValid() == false &&
m_core_module_sp.get()) {
@@ -383,13 +371,11 @@ Status ProcessMachCore::DoLoadCore() {
}
// SearchForDarwinKernel will end up calling back into this this class in
- // the GetImageInfoAddress
- // method which will give it the m_mach_kernel_addr/m_dyld_addr it already
- // has. Save that aside
- // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily
- // so
- // DynamicLoaderDarwinKernel does a real search for the kernel using its own
- // heuristics.
+ // the GetImageInfoAddress method which will give it the
+ // m_mach_kernel_addr/m_dyld_addr it already has. Save that aside and set
+ // m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so
+ // DynamicLoaderDarwinKernel does a real search for the kernel using its
+ // own heuristics.
addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
addr_t saved_user_dyld_addr = m_dyld_addr;
@@ -410,8 +396,8 @@ Status ProcessMachCore::DoLoadCore() {
}
}
- // If we found both a user-process dyld and a kernel binary, we need to decide
- // which to prefer.
+ // If we found both a user-process dyld and a kernel binary, we need to
+ // decide which to prefer.
if (GetCorefilePreference() == eKernelCorefile) {
if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
if (log)
@@ -444,18 +430,13 @@ Status ProcessMachCore::DoLoadCore() {
if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic()) {
// For non-user process core files, the permissions on the core file
- // segments are usually
- // meaningless, they may be just "read", because we're dealing with kernel
- // coredumps or
- // early startup coredumps and the dumper is grabbing pages of memory
- // without knowing
- // what they are. If they aren't marked as "exeuctable", that can break the
- // unwinder
- // which will check a pc value to see if it is in an executable segment and
- // stop the
+ // segments are usually meaningless, they may be just "read", because we're
+ // dealing with kernel coredumps or early startup coredumps and the dumper
+ // is grabbing pages of memory without knowing what they are. If they
+ // aren't marked as "exeuctable", that can break the unwinder which will
+ // check a pc value to see if it is in an executable segment and stop the
// backtrace early if it is not ("executable" and "unknown" would both be
- // fine, but
- // "not executable" will break the unwinder).
+ // fine, but "not executable" will break the unwinder).
size_t core_range_infos_size = m_core_range_infos.GetSize();
for (size_t i = 0; i < core_range_infos_size; i++) {
VMRangeToPermissions::Entry *ent =
@@ -464,8 +445,8 @@ Status ProcessMachCore::DoLoadCore() {
}
}
- // Even if the architecture is set in the target, we need to override
- // it to match the core file which is always single arch.
+ // Even if the architecture is set in the target, we need to override it to
+ // match the core file which is always single arch.
ArchSpec arch(m_core_module_sp->GetArchitecture());
if (arch.GetCore() == ArchSpec::eCore_x86_32_i486) {
arch = Platform::GetAugmentedArchSpec(GetTarget().GetPlatform().get(), "i386");
@@ -488,8 +469,7 @@ bool ProcessMachCore::UpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) {
if (old_thread_list.GetSize(false) == 0) {
// Make up the thread the first time this is called so we can setup our one
- // and only
- // core thread state.
+ // and only core thread state.
ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
if (core_objfile) {
@@ -508,8 +488,8 @@ bool ProcessMachCore::UpdateThreadList(ThreadList &old_thread_list,
}
void ProcessMachCore::RefreshStateAfterStop() {
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
+ // Let all threads recover from stopping and do any clean up based on the
+ // previous thread state (if any).
m_thread_list.RefreshStateAfterStop();
// SetThreadStopInfo (m_last_stop_packet);
}
@@ -529,8 +509,8 @@ bool ProcessMachCore::WarnBeforeDetach() const { return false; }
//------------------------------------------------------------------
size_t ProcessMachCore::ReadMemory(addr_t addr, void *buf, size_t size,
Status &error) {
- // Don't allow the caching that lldb_private::Process::ReadMemory does
- // since in core files we have it all cached our our core file anyway.
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // in core files we have it all cached our our core file anyway.
return DoReadMemory(addr, buf, size, error);
}
@@ -546,19 +526,17 @@ size_t ProcessMachCore::DoReadMemory(addr_t addr, void *buf, size_t size,
// Address Size File off File size
// ---------- ---------- ---------- ----------
// LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- --- 0
- // 0x00000000 __TEXT
- // LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 --- --- 0
- // 0x00000000 __TEXT
- // LC_SEGMENT 0x000f7000 0x00001000 0x1d60aee8 0x00001000 --- --- 0
- // 0x00000000 __TEXT
+ // 0x00000000 __TEXT LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000
+ // --- --- 0 0x00000000 __TEXT LC_SEGMENT 0x000f7000 0x00001000
+ // 0x1d60aee8 0x00001000 --- --- 0 0x00000000 __TEXT
//
// Any if the user executes the following command:
//
// (lldb) mem read 0xf6ff0
//
- // We would attempt to read 32 bytes from 0xf6ff0 but would only
- // get 16 unless we loop through consecutive memory ranges that are
- // contiguous in the address space, but not in the file data.
+ // We would attempt to read 32 bytes from 0xf6ff0 but would only get 16
+ // unless we loop through consecutive memory ranges that are contiguous in
+ // the address space, but not in the file data.
//----------------------------------------------------------------------
while (bytes_read < size) {
const addr_t curr_addr = addr + bytes_read;
@@ -641,8 +619,8 @@ void ProcessMachCore::Initialize() {
}
addr_t ProcessMachCore::GetImageInfoAddress() {
- // If we found both a user-process dyld and a kernel binary, we need to decide
- // which to prefer.
+ // If we found both a user-process dyld and a kernel binary, we need to
+ // decide which to prefer.
if (GetCorefilePreference() == eKernelCorefile) {
if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
return m_mach_kernel_addr;
diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/source/Plugins/Process/mach-core/ThreadMachCore.cpp
index 2b44105c13b1..c262dd47f978 100644
--- a/source/Plugins/Process/mach-core/ThreadMachCore.cpp
+++ b/source/Plugins/Process/mach-core/ThreadMachCore.cpp
@@ -43,7 +43,7 @@ ThreadMachCore::~ThreadMachCore() { DestroyThread(); }
const char *ThreadMachCore::GetName() {
if (m_thread_name.empty())
- return NULL;
+ return nullptr;
return m_thread_name.c_str();
}
@@ -54,8 +54,8 @@ void ThreadMachCore::RefreshStateAfterStop() {
// context by the time this function gets called. The KDPRegisterContext
// class has been made smart enough to detect when it needs to invalidate
// which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
+ // register supply functions where they check the process stop ID and do the
+ // right thing.
const bool force = false;
GetRegisterContext()->InvalidateIfNeeded(force);
}
@@ -63,8 +63,8 @@ void ThreadMachCore::RefreshStateAfterStop() {
bool ThreadMachCore::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; }
lldb::RegisterContextSP ThreadMachCore::GetRegisterContext() {
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ if (!m_reg_context_sp)
+ m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
return m_reg_context_sp;
}
@@ -89,7 +89,7 @@ ThreadMachCore::CreateRegisterContextForFrame(StackFrame *frame) {
reg_ctx_sp = m_thread_reg_ctx_sp;
} else {
Unwind *unwinder = GetUnwinder();
- if (unwinder)
+ if (unwinder != nullptr)
reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
}
return reg_ctx_sp;
diff --git a/source/Plugins/Process/minidump/CMakeLists.txt b/source/Plugins/Process/minidump/CMakeLists.txt
index 61ce16830c9b..b898ee1aa144 100644
--- a/source/Plugins/Process/minidump/CMakeLists.txt
+++ b/source/Plugins/Process/minidump/CMakeLists.txt
@@ -1,5 +1,3 @@
-include_directories(../Utility)
-
add_lldb_library(lldbPluginProcessMinidump PLUGIN
MinidumpTypes.cpp
MinidumpParser.cpp
diff --git a/source/Plugins/Process/minidump/MinidumpParser.cpp b/source/Plugins/Process/minidump/MinidumpParser.cpp
index 36350fdb6398..9a979335e99e 100644
--- a/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -14,10 +14,13 @@
// Other libraries and framework includes
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/LLDBAssert.h"
// C includes
// C++ includes
+#include <algorithm>
#include <map>
+#include <vector>
using namespace lldb_private;
using namespace minidump;
@@ -27,47 +30,11 @@ MinidumpParser::Create(const lldb::DataBufferSP &data_buf_sp) {
if (data_buf_sp->GetByteSize() < sizeof(MinidumpHeader)) {
return llvm::None;
}
-
- llvm::ArrayRef<uint8_t> header_data(data_buf_sp->GetBytes(),
- sizeof(MinidumpHeader));
- const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
-
- if (header == nullptr) {
- return llvm::None;
- }
-
- lldb::offset_t directory_list_offset = header->stream_directory_rva;
- // check if there is enough data for the parsing of the directory list
- if ((directory_list_offset +
- sizeof(MinidumpDirectory) * header->streams_count) >
- data_buf_sp->GetByteSize()) {
- return llvm::None;
- }
-
- const MinidumpDirectory *directory = nullptr;
- Status error;
- llvm::ArrayRef<uint8_t> directory_data(
- data_buf_sp->GetBytes() + directory_list_offset,
- sizeof(MinidumpDirectory) * header->streams_count);
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> directory_map;
-
- for (uint32_t i = 0; i < header->streams_count; ++i) {
- error = consumeObject(directory_data, directory);
- if (error.Fail()) {
- return llvm::None;
- }
- directory_map[static_cast<const uint32_t>(directory->stream_type)] =
- directory->location;
- }
-
- return MinidumpParser(data_buf_sp, header, std::move(directory_map));
+ return MinidumpParser(data_buf_sp);
}
-MinidumpParser::MinidumpParser(
- const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map)
- : m_data_sp(data_buf_sp), m_header(header), m_directory_map(directory_map) {
-}
+MinidumpParser::MinidumpParser(const lldb::DataBufferSP &data_buf_sp)
+ : m_data_sp(data_buf_sp) {}
llvm::ArrayRef<uint8_t> MinidumpParser::GetData() {
return llvm::ArrayRef<uint8_t>(m_data_sp->GetBytes(),
@@ -96,6 +63,31 @@ llvm::Optional<std::string> MinidumpParser::GetMinidumpString(uint32_t rva) {
return parseMinidumpString(arr_ref);
}
+UUID MinidumpParser::GetModuleUUID(const MinidumpModule *module) {
+ auto cv_record =
+ GetData().slice(module->CV_record.rva, module->CV_record.data_size);
+
+ // Read the CV record signature
+ const llvm::support::ulittle32_t *signature = nullptr;
+ Status error = consumeObject(cv_record, signature);
+ if (error.Fail())
+ return UUID();
+
+ const CvSignature cv_signature =
+ static_cast<CvSignature>(static_cast<const uint32_t>(*signature));
+
+ if (cv_signature == CvSignature::Pdb70) {
+ // PDB70 record
+ const CvRecordPdb70 *pdb70_uuid = nullptr;
+ Status error = consumeObject(cv_record, pdb70_uuid);
+ if (!error.Fail())
+ return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid));
+ } else if (cv_signature == CvSignature::ElfBuildId)
+ return UUID::fromData(cv_record);
+
+ return UUID();
+}
+
llvm::ArrayRef<MinidumpThread> MinidumpParser::GetThreads() {
llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::ThreadList);
@@ -115,12 +107,12 @@ MinidumpParser::GetThreadContext(const MinidumpThread &td) {
llvm::ArrayRef<uint8_t>
MinidumpParser::GetThreadContextWow64(const MinidumpThread &td) {
- // On Windows, a 32-bit process can run on a 64-bit machine under
- // WOW64. If the minidump was captured with a 64-bit debugger, then
- // the CONTEXT we just grabbed from the mini_dump_thread is the one
- // for the 64-bit "native" process rather than the 32-bit "guest"
- // process we care about. In this case, we can get the 32-bit CONTEXT
- // from the TEB (Thread Environment Block) of the 64-bit process.
+ // On Windows, a 32-bit process can run on a 64-bit machine under WOW64. If
+ // the minidump was captured with a 64-bit debugger, then the CONTEXT we just
+ // grabbed from the mini_dump_thread is the one for the 64-bit "native"
+ // process rather than the 32-bit "guest" process we care about. In this
+ // case, we can get the 32-bit CONTEXT from the TEB (Thread Environment
+ // Block) of the 64-bit process.
auto teb_mem = GetMemory(td.teb, sizeof(TEB64));
if (teb_mem.empty())
return {};
@@ -130,9 +122,9 @@ MinidumpParser::GetThreadContextWow64(const MinidumpThread &td) {
if (error.Fail())
return {};
- // Slot 1 of the thread-local storage in the 64-bit TEB points to a
- // structure that includes the 32-bit CONTEXT (after a ULONG).
- // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx
+ // Slot 1 of the thread-local storage in the 64-bit TEB points to a structure
+ // that includes the 32-bit CONTEXT (after a ULONG). See:
+ // https://msdn.microsoft.com/en-us/library/ms681670.aspx
auto context =
GetMemory(wow64teb->tls_slots[1] + 4, sizeof(MinidumpContext_x86_32));
if (context.size() < sizeof(MinidumpContext_x86_32))
@@ -334,10 +326,10 @@ MinidumpParser::FindMemoryRange(lldb::addr_t addr) {
}
}
- // Some Minidumps have a Memory64ListStream that captures all the heap
- // memory (full-memory Minidumps). We can't exactly use the same loop as
- // above, because the Minidump uses slightly different data structures to
- // describe those
+ // Some Minidumps have a Memory64ListStream that captures all the heap memory
+ // (full-memory Minidumps). We can't exactly use the same loop as above,
+ // because the Minidump uses slightly different data structures to describe
+ // those
if (!data64.empty()) {
llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
@@ -377,8 +369,8 @@ llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr,
return {};
// There's at least some overlap between the beginning of the desired range
- // (addr) and the current range. Figure out where the overlap begins and
- // how much overlap there is.
+ // (addr) and the current range. Figure out where the overlap begins and how
+ // much overlap there is.
const size_t offset = addr - range->start;
@@ -456,3 +448,109 @@ MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
// appear truncated.
return info;
}
+
+Status MinidumpParser::Initialize() {
+ Status error;
+
+ lldbassert(m_directory_map.empty());
+
+ llvm::ArrayRef<uint8_t> header_data(m_data_sp->GetBytes(),
+ sizeof(MinidumpHeader));
+ const MinidumpHeader *header = MinidumpHeader::Parse(header_data);
+ if (header == nullptr) {
+ error.SetErrorString("invalid minidump: can't parse the header");
+ return error;
+ }
+
+ // A minidump without at least one stream is clearly ill-formed
+ if (header->streams_count == 0) {
+ error.SetErrorString("invalid minidump: no streams present");
+ return error;
+ }
+
+ struct FileRange {
+ uint32_t offset = 0;
+ uint32_t size = 0;
+
+ FileRange(uint32_t offset, uint32_t size) : offset(offset), size(size) {}
+ uint32_t end() const { return offset + size; }
+ };
+
+ const uint32_t file_size = m_data_sp->GetByteSize();
+
+ // Build a global minidump file map, checking for:
+ // - overlapping streams/data structures
+ // - truncation (streams pointing past the end of file)
+ std::vector<FileRange> minidump_map;
+
+ // Add the minidump header to the file map
+ if (sizeof(MinidumpHeader) > file_size) {
+ error.SetErrorString("invalid minidump: truncated header");
+ return error;
+ }
+ minidump_map.emplace_back( 0, sizeof(MinidumpHeader) );
+
+ // Add the directory entries to the file map
+ FileRange directory_range(header->stream_directory_rva,
+ header->streams_count *
+ sizeof(MinidumpDirectory));
+ if (directory_range.end() > file_size) {
+ error.SetErrorString("invalid minidump: truncated streams directory");
+ return error;
+ }
+ minidump_map.push_back(directory_range);
+
+ // Parse stream directory entries
+ llvm::ArrayRef<uint8_t> directory_data(
+ m_data_sp->GetBytes() + directory_range.offset, directory_range.size);
+ for (uint32_t i = 0; i < header->streams_count; ++i) {
+ const MinidumpDirectory *directory_entry = nullptr;
+ error = consumeObject(directory_data, directory_entry);
+ if (error.Fail())
+ return error;
+ if (directory_entry->stream_type == 0) {
+ // Ignore dummy streams (technically ill-formed, but a number of
+ // existing minidumps seem to contain such streams)
+ if (directory_entry->location.data_size == 0)
+ continue;
+ error.SetErrorString("invalid minidump: bad stream type");
+ return error;
+ }
+ // Update the streams map, checking for duplicate stream types
+ if (!m_directory_map
+ .insert({directory_entry->stream_type, directory_entry->location})
+ .second) {
+ error.SetErrorString("invalid minidump: duplicate stream type");
+ return error;
+ }
+ // Ignore the zero-length streams for layout checks
+ if (directory_entry->location.data_size != 0) {
+ minidump_map.emplace_back(directory_entry->location.rva,
+ directory_entry->location.data_size);
+ }
+ }
+
+ // Sort the file map ranges by start offset
+ std::sort(minidump_map.begin(), minidump_map.end(),
+ [](const FileRange &a, const FileRange &b) {
+ return a.offset < b.offset;
+ });
+
+ // Check for overlapping streams/data structures
+ for (size_t i = 1; i < minidump_map.size(); ++i) {
+ const auto &prev_range = minidump_map[i - 1];
+ if (prev_range.end() > minidump_map[i].offset) {
+ error.SetErrorString("invalid minidump: overlapping streams");
+ return error;
+ }
+ }
+
+ // Check for streams past the end of file
+ const auto &last_range = minidump_map.back();
+ if (last_range.end() > file_size) {
+ error.SetErrorString("invalid minidump: truncated stream");
+ return error;
+ }
+
+ return error;
+}
diff --git a/source/Plugins/Process/minidump/MinidumpParser.h b/source/Plugins/Process/minidump/MinidumpParser.h
index b7329ffc0028..49b1eef14de5 100644
--- a/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/source/Plugins/Process/minidump/MinidumpParser.h
@@ -17,6 +17,7 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Status.h"
+#include "lldb/Utility/UUID.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -54,6 +55,8 @@ public:
llvm::Optional<std::string> GetMinidumpString(uint32_t rva);
+ UUID GetModuleUUID(const MinidumpModule* module);
+
llvm::ArrayRef<MinidumpThread> GetThreads();
llvm::ArrayRef<uint8_t> GetThreadContext(const MinidumpThread &td);
@@ -86,14 +89,15 @@ public:
llvm::Optional<MemoryRegionInfo> GetMemoryRegionInfo(lldb::addr_t);
+ // Perform consistency checks and initialize internal data structures
+ Status Initialize();
+
+private:
+ MinidumpParser(const lldb::DataBufferSP &data_buf_sp);
+
private:
lldb::DataBufferSP m_data_sp;
- const MinidumpHeader *m_header;
llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map;
-
- MinidumpParser(
- const lldb::DataBufferSP &data_buf_sp, const MinidumpHeader *header,
- llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &&directory_map);
};
} // end namespace minidump
diff --git a/source/Plugins/Process/minidump/MinidumpTypes.cpp b/source/Plugins/Process/minidump/MinidumpTypes.cpp
index 24ce3f94c094..049704ba80ca 100644
--- a/source/Plugins/Process/minidump/MinidumpTypes.cpp
+++ b/source/Plugins/Process/minidump/MinidumpTypes.cpp
@@ -33,9 +33,6 @@ const MinidumpHeader *MinidumpHeader::Parse(llvm::ArrayRef<uint8_t> &data) {
version != MinidumpHeaderConstants::Version)
return nullptr;
- // TODO check for max number of streams ?
- // TODO more sanity checks ?
-
return header;
}
@@ -44,19 +41,23 @@ llvm::Optional<std::string>
lldb_private::minidump::parseMinidumpString(llvm::ArrayRef<uint8_t> &data) {
std::string result;
- const uint32_t *source_length;
- Status error = consumeObject(data, source_length);
- if (error.Fail() || *source_length > data.size() || *source_length % 2 != 0)
+ const uint32_t *source_length_ptr;
+ Status error = consumeObject(data, source_length_ptr);
+
+ // Copy non-aligned source_length data into aligned memory.
+ uint32_t source_length;
+ std::memcpy(&source_length, source_length_ptr, sizeof(source_length));
+
+ if (error.Fail() || source_length > data.size() || source_length % 2 != 0)
return llvm::None;
auto source_start = reinterpret_cast<const llvm::UTF16 *>(data.data());
- // source_length is the length of the string in bytes
- // we need the length of the string in UTF-16 characters/code points (16 bits
- // per char)
- // that's why it's divided by 2
- const auto source_end = source_start + (*source_length) / 2;
+ // source_length is the length of the string in bytes we need the length of
+ // the string in UTF-16 characters/code points (16 bits per char) that's why
+ // it's divided by 2
+ const auto source_end = source_start + source_length / 2;
// resize to worst case length
- result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * (*source_length) / 2);
+ result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * source_length / 2);
auto result_start = reinterpret_cast<llvm::UTF8 *>(&result[0]);
const auto result_end = result_start + result.size();
llvm::ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end,
@@ -80,11 +81,17 @@ const MinidumpThread *MinidumpThread::Parse(llvm::ArrayRef<uint8_t> &data) {
llvm::ArrayRef<MinidumpThread>
MinidumpThread::ParseThreadList(llvm::ArrayRef<uint8_t> &data) {
+ const auto orig_size = data.size();
const llvm::support::ulittle32_t *thread_count;
Status error = consumeObject(data, thread_count);
if (error.Fail() || *thread_count * sizeof(MinidumpThread) > data.size())
return {};
+ // Compilers might end up padding an extra 4 bytes depending on how the
+ // structure is padded by the compiler and the #pragma pack settings.
+ if (4 + *thread_count * sizeof(MinidumpThread) < orig_size)
+ data = data.drop_front(4);
+
return llvm::ArrayRef<MinidumpThread>(
reinterpret_cast<const MinidumpThread *>(data.data()), *thread_count);
}
@@ -156,12 +163,17 @@ const MinidumpModule *MinidumpModule::Parse(llvm::ArrayRef<uint8_t> &data) {
llvm::ArrayRef<MinidumpModule>
MinidumpModule::ParseModuleList(llvm::ArrayRef<uint8_t> &data) {
-
+ const auto orig_size = data.size();
const llvm::support::ulittle32_t *modules_count;
Status error = consumeObject(data, modules_count);
if (error.Fail() || *modules_count * sizeof(MinidumpModule) > data.size())
return {};
-
+
+ // Compilers might end up padding an extra 4 bytes depending on how the
+ // structure is padded by the compiler and the #pragma pack settings.
+ if (4 + *modules_count * sizeof(MinidumpModule) < orig_size)
+ data = data.drop_front(4);
+
return llvm::ArrayRef<MinidumpModule>(
reinterpret_cast<const MinidumpModule *>(data.data()), *modules_count);
}
@@ -179,11 +191,17 @@ MinidumpExceptionStream::Parse(llvm::ArrayRef<uint8_t> &data) {
llvm::ArrayRef<MinidumpMemoryDescriptor>
MinidumpMemoryDescriptor::ParseMemoryList(llvm::ArrayRef<uint8_t> &data) {
+ const auto orig_size = data.size();
const llvm::support::ulittle32_t *mem_ranges_count;
Status error = consumeObject(data, mem_ranges_count);
if (error.Fail() ||
*mem_ranges_count * sizeof(MinidumpMemoryDescriptor) > data.size())
return {};
+
+ // Compilers might end up padding an extra 4 bytes depending on how the
+ // structure is padded by the compiler and the #pragma pack settings.
+ if (4 + *mem_ranges_count * sizeof(MinidumpMemoryDescriptor) < orig_size)
+ data = data.drop_front(4);
return llvm::makeArrayRef(
reinterpret_cast<const MinidumpMemoryDescriptor *>(data.data()),
diff --git a/source/Plugins/Process/minidump/MinidumpTypes.h b/source/Plugins/Process/minidump/MinidumpTypes.h
index 6de4f55a769d..e83089865b9e 100644
--- a/source/Plugins/Process/minidump/MinidumpTypes.h
+++ b/source/Plugins/Process/minidump/MinidumpTypes.h
@@ -43,6 +43,21 @@ enum class MinidumpHeaderConstants : uint32_t {
};
+enum class CvSignature : uint32_t {
+ Pdb70 = 0x53445352, // RSDS
+ ElfBuildId = 0x4270454c, // BpEL (Breakpad/Crashpad minidumps)
+};
+
+// Reference:
+// https://crashpad.chromium.org/doxygen/structcrashpad_1_1CodeViewRecordPDB70.html
+struct CvRecordPdb70 {
+ uint8_t Uuid[16];
+ llvm::support::ulittle32_t Age;
+ // char PDBFileName[];
+};
+static_assert(sizeof(CvRecordPdb70) == 20,
+ "sizeof CvRecordPdb70 is not correct!");
+
// Reference:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680394.aspx
enum class MinidumpStreamType : uint32_t {
diff --git a/source/Plugins/Process/minidump/ProcessMinidump.cpp b/source/Plugins/Process/minidump/ProcessMinidump.cpp
index d4d65c044eab..b43f22382eac 100644
--- a/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/State.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/DataBufferLLVM.h"
@@ -31,9 +32,56 @@
// C includes
// C++ includes
+using namespace lldb;
using namespace lldb_private;
using namespace minidump;
+//------------------------------------------------------------------
+/// A placeholder module used for minidumps, where the original
+/// object files may not be available (so we can't parse the object
+/// files to extract the set of sections/segments)
+///
+/// This placeholder module has a single synthetic section (.module_image)
+/// which represents the module memory range covering the whole module.
+//------------------------------------------------------------------
+class PlaceholderModule : public Module {
+public:
+ PlaceholderModule(const ModuleSpec &module_spec) :
+ Module(module_spec.GetFileSpec(), module_spec.GetArchitecture()) {
+ if (module_spec.GetUUID().IsValid())
+ SetUUID(module_spec.GetUUID());
+ }
+
+ // Creates a synthetic module section covering the whole module image (and
+ // sets the section load address as well)
+ void CreateImageSection(const MinidumpModule *module, Target& target) {
+ const ConstString section_name(".module_image");
+ lldb::SectionSP section_sp(new Section(
+ shared_from_this(), // Module to which this section belongs.
+ nullptr, // ObjectFile
+ 0, // Section ID.
+ section_name, // Section name.
+ eSectionTypeContainer, // Section type.
+ module->base_of_image, // VM address.
+ module->size_of_image, // VM size in bytes of this section.
+ 0, // Offset of this section in the file.
+ module->size_of_image, // Size of the section as found in the file.
+ 12, // Alignment of the section (log2)
+ 0, // Flags for this section.
+ 1)); // Number of host bytes per target byte
+ section_sp->SetPermissions(ePermissionsExecutable | ePermissionsReadable);
+ GetSectionList()->AddSection(section_sp);
+ target.GetSectionLoadList().SetSectionLoadAddress(
+ section_sp, module->base_of_image);
+ }
+
+ ObjectFile *GetObjectFile() override { return nullptr; }
+
+ SectionList *GetSectionList() override {
+ return Module::GetUnifiedSectionList();
+ }
+};
+
ConstString ProcessMinidump::GetPluginNameStatic() {
static ConstString g_name("minidump");
return g_name;
@@ -57,7 +105,7 @@ lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp,
if (!DataPtr)
return nullptr;
- assert(DataPtr->GetByteSize() == header_size);
+ lldbassert(DataPtr->GetByteSize() == header_size);
// first, only try to parse the header, beacuse we need to be fast
llvm::ArrayRef<uint8_t> HeaderBytes = DataPtr->GetData();
@@ -92,10 +140,10 @@ ProcessMinidump::ProcessMinidump(lldb::TargetSP target_sp,
ProcessMinidump::~ProcessMinidump() {
Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
+ // We need to call finalize on the process before destroying ourselves to
+ // make sure all of the broadcaster cleanup goes as planned. If we destruct
+ // this class, then Process::~Process() might have problems trying to fully
+ // destroy the broadcaster.
Finalize();
}
@@ -116,10 +164,29 @@ void ProcessMinidump::Terminate() {
Status ProcessMinidump::DoLoadCore() {
Status error;
+ // Minidump parser initialization & consistency checks
+ error = m_minidump_parser.Initialize();
+ if (error.Fail())
+ return error;
+
+ // Do we support the minidump's architecture?
+ ArchSpec arch = GetArchitecture();
+ switch (arch.GetMachine()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ // supported
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unsupported minidump architecture: %s",
+ arch.GetArchitectureName());
+ return error;
+ }
+
m_thread_list = m_minidump_parser.GetThreads();
m_active_exception = m_minidump_parser.GetExceptionStream();
ReadModuleList();
- GetTarget().SetArchitecture(GetArchitecture());
+ GetTarget().SetArchitecture(arch);
llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid();
if (!pid) {
@@ -185,8 +252,8 @@ bool ProcessMinidump::WarnBeforeDetach() const { return false; }
size_t ProcessMinidump::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
Status &error) {
- // Don't allow the caching that lldb_private::Process::ReadMemory does
- // since we have it all cached in our dump file anyway.
+ // Don't allow the caching that lldb_private::Process::ReadMemory does since
+ // we have it all cached in our dump file anyway.
return DoReadMemory(addr, buf, size, error);
}
@@ -276,12 +343,25 @@ void ProcessMinidump::ReadModuleList() {
m_is_wow64 = true;
}
- const auto file_spec = FileSpec(name.getValue(), true);
- ModuleSpec module_spec = file_spec;
+ const auto uuid = m_minidump_parser.GetModuleUUID(module);
+ const auto file_spec =
+ FileSpec(name.getValue(), true, GetArchitecture().GetTriple());
+ ModuleSpec module_spec(file_spec, uuid);
Status error;
lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error);
if (!module_sp || error.Fail()) {
- continue;
+ // We failed to locate a matching local object file. Fortunately, the
+ // minidump format encodes enough information about each module's memory
+ // range to allow us to create placeholder modules.
+ //
+ // This enables most LLDB functionality involving address-to-module
+ // translations (ex. identifing the module for a stack frame PC) and
+ // modules/sections commands (ex. target modules list, ...)
+ auto placeholder_module =
+ std::make_shared<PlaceholderModule>(module_spec);
+ placeholder_module->CreateImageSection(module, GetTarget());
+ module_sp = placeholder_module;
+ GetTarget().GetImages().Append(module_sp);
}
if (log) {
diff --git a/source/Plugins/Process/minidump/ProcessMinidump.h b/source/Plugins/Process/minidump/ProcessMinidump.h
index 4b91d1ba396a..d65ada9009a7 100644
--- a/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -61,6 +61,8 @@ public:
uint32_t GetPluginVersion() override;
+ SystemRuntime *GetSystemRuntime() override { return nullptr; }
+
Status DoDestroy() override;
void RefreshStateAfterStop() override;
diff --git a/source/Plugins/ScriptInterpreter/CMakeLists.txt b/source/Plugins/ScriptInterpreter/CMakeLists.txt
index dc2a27d95a31..5d8642eb07e6 100644
--- a/source/Plugins/ScriptInterpreter/CMakeLists.txt
+++ b/source/Plugins/ScriptInterpreter/CMakeLists.txt
@@ -1,2 +1,4 @@
add_subdirectory(None)
-add_subdirectory(Python)
+if (NOT LLDB_DISABLE_PYTHON)
+ add_subdirectory(Python)
+endif()
diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
index 9ec9f4344613..4bd4c6a029a0 100644
--- a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
+++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
@@ -27,7 +27,7 @@ ScriptInterpreterNone::ScriptInterpreterNone(CommandInterpreter &interpreter)
ScriptInterpreterNone::~ScriptInterpreterNone() {}
-bool ScriptInterpreterNone::ExecuteOneLine(const char *command,
+bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command,
CommandReturnObject *,
const ExecuteScriptOptions &) {
m_interpreter.GetDebugger().GetErrorFile()->PutCString(
diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
index d66b2f07310c..824579472b5e 100644
--- a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
+++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
@@ -25,7 +25,7 @@ public:
~ScriptInterpreterNone() override;
bool ExecuteOneLine(
- const char *command, CommandReturnObject *result,
+ llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
void ExecuteInterpreterLoop() override;
diff --git a/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
index c337fc7b5874..56eacc941d64 100644
--- a/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
+++ b/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt
@@ -1,3 +1,16 @@
+if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
+ # Call a python script to gather the arch-specific libdir for
+ # modules like the lldb module.
+ execute_process(
+ COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../../../../scripts/get_relative_lib_dir.py
+ RESULT_VARIABLE get_libdir_status
+ OUTPUT_VARIABLE relative_libdir
+ )
+ if (get_libdir_status EQUAL 0)
+ add_definitions(-DLLDB_PYTHON_RELATIVE_LIBDIR="${relative_libdir}")
+ endif()
+endif()
+
add_lldb_library(lldbPluginScriptInterpreterPython PLUGIN
PythonDataObjects.cpp
PythonExceptionState.cpp
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 966bdff3ad95..90d8ab97fb73 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -1,5 +1,4 @@
-//===-- PythonDataObjects.cpp ------------------------------------*- C++
-//-*-===//
+//===-- PythonDataObjects.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -123,21 +122,20 @@ PythonObject::ResolveNameWithDictionary(llvm::StringRef name,
}
PythonObject PythonObject::ResolveName(llvm::StringRef name) const {
- // Resolve the name in the context of the specified object. If,
- // for example, `this` refers to a PyModule, then this will look for
- // `name` in this module. If `this` refers to a PyType, then it will
- // resolve `name` as an attribute of that type. If `this` refers to
- // an instance of an object, then it will resolve `name` as the value
- // of the specified field.
+ // Resolve the name in the context of the specified object. If, for example,
+ // `this` refers to a PyModule, then this will look for `name` in this
+ // module. If `this` refers to a PyType, then it will resolve `name` as an
+ // attribute of that type. If `this` refers to an instance of an object,
+ // then it will resolve `name` as the value of the specified field.
//
// This function handles dotted names so that, for example, if `m_py_obj`
- // refers to the `sys` module, and `name` == "path.append", then it
- // will find the function `sys.path.append`.
+ // refers to the `sys` module, and `name` == "path.append", then it will find
+ // the function `sys.path.append`.
size_t dot_pos = name.find_first_of('.');
if (dot_pos == llvm::StringRef::npos) {
- // No dots in the name, we should be able to find the value immediately
- // as an attribute of `m_py_obj`.
+ // No dots in the name, we should be able to find the value immediately as
+ // an attribute of `m_py_obj`.
return GetAttributeValue(name);
}
@@ -230,8 +228,8 @@ bool PythonBytes::Check(PyObject *py_obj) {
}
void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonBytes::Check(py_obj)) {
@@ -240,8 +238,7 @@ void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -303,8 +300,8 @@ bool PythonByteArray::Check(PyObject *py_obj) {
}
void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonByteArray::Check(py_obj)) {
@@ -313,8 +310,7 @@ void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -378,8 +374,8 @@ bool PythonString::Check(PyObject *py_obj) {
}
void PythonString::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonString::Check(py_obj)) {
@@ -394,8 +390,7 @@ void PythonString::Reset(PyRefType type, PyObject *py_obj) {
result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
#endif
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -404,14 +399,16 @@ llvm::StringRef PythonString::GetString() const {
return llvm::StringRef();
Py_ssize_t size;
- char *c;
+ const char *data;
#if PY_MAJOR_VERSION >= 3
- c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
+ data = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
#else
+ char *c;
PyString_AsStringAndSize(m_py_obj, &c, &size);
+ data = c;
#endif
- return llvm::StringRef(c, size);
+ return llvm::StringRef(data, size);
}
size_t PythonString::GetSize() const {
@@ -466,8 +463,8 @@ bool PythonInteger::Check(PyObject *py_obj) {
return false;
#if PY_MAJOR_VERSION >= 3
- // Python 3 does not have PyInt_Check. There is only one type of
- // integral value, long.
+ // Python 3 does not have PyInt_Check. There is only one type of integral
+ // value, long.
return PyLong_Check(py_obj);
#else
return PyLong_Check(py_obj) || PyInt_Check(py_obj);
@@ -475,8 +472,8 @@ bool PythonInteger::Check(PyObject *py_obj) {
}
void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonInteger::Check(py_obj)) {
@@ -485,13 +482,13 @@ void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
}
#if PY_MAJOR_VERSION < 3
- // Always store this as a PyLong, which makes interoperability between
- // Python 2.x and Python 3.x easier. This is only necessary in 2.x,
- // since 3.x doesn't even have a PyInt.
+ // Always store this as a PyLong, which makes interoperability between Python
+ // 2.x and Python 3.x easier. This is only necessary in 2.x, since 3.x
+ // doesn't even have a PyInt.
if (PyInt_Check(py_obj)) {
// Since we converted the original object to a different type, the new
- // object is an owned object regardless of the ownership semantics requested
- // by the user.
+ // object is an owned object regardless of the ownership semantics
+ // requested by the user.
result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
}
#endif
@@ -500,8 +497,7 @@ void PythonInteger::Reset(PyRefType type, PyObject *py_obj) {
"Couldn't get a PyLong from this PyObject");
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -513,10 +509,9 @@ int64_t PythonInteger::GetInteger() const {
int overflow = 0;
int64_t result = PyLong_AsLongLongAndOverflow(m_py_obj, &overflow);
if (overflow != 0) {
- // We got an integer that overflows, like 18446744072853913392L
- // we can't use PyLong_AsLongLong() as it will return
- // 0xffffffffffffffff. If we use the unsigned long long
- // it will work as expected.
+ // We got an integer that overflows, like 18446744072853913392L we can't
+ // use PyLong_AsLongLong() as it will return 0xffffffffffffffff. If we
+ // use the unsigned long long it will work as expected.
const uint64_t uval = PyLong_AsUnsignedLongLong(m_py_obj);
result = static_cast<int64_t>(uval);
}
@@ -563,8 +558,8 @@ bool PythonList::Check(PyObject *py_obj) {
}
void PythonList::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonList::Check(py_obj)) {
@@ -573,8 +568,7 @@ void PythonList::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -668,8 +662,8 @@ bool PythonTuple::Check(PyObject *py_obj) {
}
void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonTuple::Check(py_obj)) {
@@ -678,8 +672,7 @@ void PythonTuple::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -741,8 +734,8 @@ bool PythonDictionary::Check(PyObject *py_obj) {
}
void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonDictionary::Check(py_obj)) {
@@ -751,8 +744,7 @@ void PythonDictionary::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -833,8 +825,8 @@ bool PythonModule::Check(PyObject *py_obj) {
}
void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonModule::Check(py_obj)) {
@@ -843,8 +835,7 @@ void PythonModule::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -871,8 +862,8 @@ bool PythonCallable::Check(PyObject *py_obj) {
}
void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonCallable::Check(py_obj)) {
@@ -881,8 +872,7 @@ void PythonCallable::Reset(PyRefType type, PyObject *py_obj) {
}
// Calling PythonObject::Reset(const PythonObject&) will lead to stack
- // overflow since it calls
- // back into the virtual implementation.
+ // overflow since it calls back into the virtual implementation.
PythonObject::Reset(PyRefType::Borrowed, result.get());
}
@@ -963,9 +953,9 @@ bool PythonFile::Check(PyObject *py_obj) {
#else
// In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
// first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
- // over `io.open()`, which returns some object derived from `io.IOBase`.
- // As a result, the only way to detect a file in Python 3 is to check whether
- // it inherits from `io.IOBase`. Since it is possible for non-files to also
+ // over `io.open()`, which returns some object derived from `io.IOBase`. As a
+ // result, the only way to detect a file in Python 3 is to check whether it
+ // inherits from `io.IOBase`. Since it is possible for non-files to also
// inherit from `io.IOBase`, we additionally verify that it has the `fileno`
// attribute, which should guarantee that it is backed by the file system.
PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
@@ -985,8 +975,8 @@ bool PythonFile::Check(PyObject *py_obj) {
}
void PythonFile::Reset(PyRefType type, PyObject *py_obj) {
- // Grab the desired reference type so that if we end up rejecting
- // `py_obj` it still gets decremented if necessary.
+ // Grab the desired reference type so that if we end up rejecting `py_obj` it
+ // still gets decremented if necessary.
PythonObject result(type, py_obj);
if (!PythonFile::Check(py_obj)) {
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
index 4d956d5dbe14..d28a8033820a 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
@@ -30,9 +30,9 @@ PythonExceptionState::~PythonExceptionState() {
}
void PythonExceptionState::Acquire(bool restore_on_exit) {
- // If a state is already acquired, the user needs to decide whether they
- // want to discard or restore it. Don't allow the potential silent
- // loss of a valid state.
+ // If a state is already acquired, the user needs to decide whether they want
+ // to discard or restore it. Don't allow the potential silent loss of a
+ // valid state.
assert(!IsError());
if (!HasErrorOccurred())
@@ -45,8 +45,7 @@ void PythonExceptionState::Acquire(bool restore_on_exit) {
// PyErr_Fetch clears the error flag.
assert(!HasErrorOccurred());
- // Ownership of the objects returned by `PyErr_Fetch` is transferred
- // to us.
+ // Ownership of the objects returned by `PyErr_Fetch` is transferred to us.
m_type.Reset(PyRefType::Owned, py_type);
m_value.Reset(PyRefType::Owned, py_value);
m_traceback.Reset(PyRefType::Owned, py_traceback);
@@ -56,14 +55,14 @@ void PythonExceptionState::Acquire(bool restore_on_exit) {
void PythonExceptionState::Restore() {
if (m_type.IsValid()) {
// The documentation for PyErr_Restore says "Do not pass a null type and
- // non-null value or traceback. So only restore if type was non-null
- // to begin with. In this case we're passing ownership back to Python
- // so release them all.
+ // non-null value or traceback. So only restore if type was non-null to
+ // begin with. In this case we're passing ownership back to Python so
+ // release them all.
PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
}
- // After we restore, we should not hold onto the exception state. Demand that
- // it be re-acquired.
+ // After we restore, we should not hold onto the exception state. Demand
+ // that it be re-acquired.
Discard();
}
@@ -100,10 +99,10 @@ std::string PythonExceptionState::Format() const {
if (!IsError())
return std::string();
- // It's possible that ReadPythonBacktrace generated another exception.
- // If this happens we have to clear the exception, because otherwise
- // PyObject_Str() will assert below. That's why we needed to do the
- // save / restore at the beginning of this function.
+ // It's possible that ReadPythonBacktrace generated another exception. If
+ // this happens we have to clear the exception, because otherwise
+ // PyObject_Str() will assert below. That's why we needed to do the save /
+ // restore at the beginning of this function.
PythonExceptionState bt_error_state(false);
std::string error_string;
@@ -114,8 +113,8 @@ std::string PythonExceptionState::Format() const {
// If we were able to read the backtrace, just append it.
error_stream << backtrace << "\n";
} else {
- // Otherwise, append some information about why we were unable to
- // obtain the backtrace.
+ // Otherwise, append some information about why we were unable to obtain
+ // the backtrace.
PythonString bt_error = bt_error_state.GetValue().Str();
error_stream << "An error occurred while retrieving the backtrace: "
<< bt_error.GetString() << "\n";
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 6c39690268c6..b8eb36a2baf6 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -112,13 +112,12 @@ static bool g_initialized = false;
namespace {
-// Initializing Python is not a straightforward process. We cannot control what
-// external code may have done before getting to this point in LLDB, including
-// potentially having already initialized Python, so we need to do a lot of work
-// to ensure that the existing state of the system is maintained across our
-// initialization. We do this by using an RAII pattern where we save off
-// initial
-// state at the beginning, and restore it at the end
+// Initializing Python is not a straightforward process. We cannot control
+// what external code may have done before getting to this point in LLDB,
+// including potentially having already initialized Python, so we need to do a
+// lot of work to ensure that the existing state of the system is maintained
+// across our initialization. We do this by using an RAII pattern where we
+// save off initial state at the beginning, and restore it at the end
struct InitializePythonRAII {
public:
InitializePythonRAII()
@@ -210,12 +209,11 @@ bool ScriptInterpreterPython::Locker::DoAcquireLock() {
LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked",
m_GILState == PyGILState_UNLOCKED ? "un" : "");
- // we need to save the thread state when we first start the command
- // because we might decide to interrupt it while some action is taking
- // place outside of Python (e.g. printing to screen, waiting for the network,
- // ...)
- // in that case, _PyThreadState_Current will be NULL - and we would be unable
- // to set the asynchronous exception - not a desirable situation
+ // we need to save the thread state when we first start the command because
+ // we might decide to interrupt it while some action is taking place outside
+ // of Python (e.g. printing to screen, waiting for the network, ...) in that
+ // case, _PyThreadState_Current will be NULL - and we would be unable to set
+ // the asynchronous exception - not a desirable situation
m_python_interpreter->SetThreadState(PyThreadState_Get());
m_python_interpreter->IncrementLockCount();
return true;
@@ -281,17 +279,16 @@ ScriptInterpreterPython::ScriptInterpreterPython(
PyRun_SimpleString(run_string.GetData());
// Reloading modules requires a different syntax in Python 2 and Python 3.
- // This provides
- // a consistent syntax no matter what version of Python.
+ // This provides a consistent syntax no matter what version of Python.
run_string.Clear();
run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')",
m_dictionary_name.c_str());
PyRun_SimpleString(run_string.GetData());
// WARNING: temporary code that loads Cocoa formatters - this should be done
- // on a per-platform basis rather than loading the whole set
- // and letting the individual formatter classes exploit APIs to check whether
- // they can/cannot do their task
+ // on a per-platform basis rather than loading the whole set and letting the
+ // individual formatter classes exploit APIs to check whether they can/cannot
+ // do their task
run_string.Clear();
run_string.Printf(
"run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')",
@@ -314,13 +311,11 @@ ScriptInterpreterPython::ScriptInterpreterPython(
}
ScriptInterpreterPython::~ScriptInterpreterPython() {
- // the session dictionary may hold objects with complex state
- // which means that they may need to be torn down with some level of smarts
- // and that, in turn, requires a valid thread state
- // force Python to procure itself such a thread state, nuke the session
- // dictionary
- // and then release it for others to use and proceed with the rest of the
- // shutdown
+ // the session dictionary may hold objects with complex state which means
+ // that they may need to be torn down with some level of smarts and that, in
+ // turn, requires a valid thread state force Python to procure itself such a
+ // thread state, nuke the session dictionary and then release it for others
+ // to use and proceed with the rest of the shutdown
auto gil_state = PyGILState_Ensure();
m_session_dict.Reset();
PyGILState_Release(gil_state);
@@ -352,6 +347,71 @@ const char *ScriptInterpreterPython::GetPluginDescriptionStatic() {
return "Embedded Python interpreter";
}
+void ScriptInterpreterPython::ComputePythonDirForApple(
+ llvm::SmallVectorImpl<char> &path) {
+ auto style = llvm::sys::path::Style::posix;
+
+ llvm::StringRef path_ref(path.begin(), path.size());
+ auto rbegin = llvm::sys::path::rbegin(path_ref, style);
+ auto rend = llvm::sys::path::rend(path_ref);
+ auto framework = std::find(rbegin, rend, "LLDB.framework");
+ if (framework == rend) {
+ ComputePythonDirForPosix(path);
+ return;
+ }
+ path.resize(framework - rend);
+ llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");
+}
+
+void ScriptInterpreterPython::ComputePythonDirForPosix(
+ llvm::SmallVectorImpl<char> &path) {
+ auto style = llvm::sys::path::Style::posix;
+#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
+ // Build the path by backing out of the lib dir, then building with whatever
+ // the real python interpreter uses. (e.g. lib for most, lib64 on RHEL
+ // x86_64).
+ llvm::sys::path::remove_filename(path, style);
+ llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR);
+#else
+ llvm::sys::path::append(path, style,
+ "python" + llvm::Twine(PY_MAJOR_VERSION) + "." +
+ llvm::Twine(PY_MINOR_VERSION),
+ "site-packages");
+#endif
+}
+
+void ScriptInterpreterPython::ComputePythonDirForWindows(
+ llvm::SmallVectorImpl<char> &path) {
+ auto style = llvm::sys::path::Style::windows;
+ llvm::sys::path::remove_filename(path, style);
+ llvm::sys::path::append(path, style, "lib", "site-packages");
+
+ // This will be injected directly through FileSpec.GetDirectory().SetString(),
+ // so we need to normalize manually.
+ std::replace(path.begin(), path.end(), '\\', '/');
+}
+
+FileSpec ScriptInterpreterPython::GetPythonDir() {
+ static FileSpec g_spec = []() {
+ FileSpec spec = HostInfo::GetShlibDir();
+ if (!spec)
+ return FileSpec();
+ llvm::SmallString<64> path;
+ spec.GetPath(path);
+
+#if defined(__APPLE__)
+ ComputePythonDirForApple(path);
+#elif defined(_WIN32)
+ ComputePythonDirForWindows(path);
+#else
+ ComputePythonDirForPosix(path);
+#endif
+ spec.GetDirectory().SetString(path);
+ return spec;
+ }();
+ return g_spec;
+}
+
lldb_private::ConstString ScriptInterpreterPython::GetPluginName() {
return GetPluginNameStatic();
}
@@ -452,16 +512,16 @@ void ScriptInterpreterPython::ResetOutputFileHandle(FILE *fh) {}
void ScriptInterpreterPython::SaveTerminalState(int fd) {
// Python mucks with the terminal state of STDIN. If we can possibly avoid
// this by setting the file handles up correctly prior to entering the
- // interpreter we should. For now we save and restore the terminal state
- // on the input file handle.
+ // interpreter we should. For now we save and restore the terminal state on
+ // the input file handle.
m_terminal_state.Save(fd, false);
}
void ScriptInterpreterPython::RestoreTerminalState() {
// Python mucks with the terminal state of STDIN. If we can possibly avoid
// this by setting the file handles up correctly prior to entering the
- // interpreter we should. For now we save and restore the terminal state
- // on the input file handle.
+ // interpreter we should. For now we save and restore the terminal state on
+ // the input file handle.
m_terminal_state.Restore();
}
@@ -470,14 +530,11 @@ void ScriptInterpreterPython::LeaveSession() {
if (log)
log->PutCString("ScriptInterpreterPython::LeaveSession()");
- // checking that we have a valid thread state - since we use our own threading
- // and locking
- // in some (rare) cases during cleanup Python may end up believing we have no
- // thread state
- // and PyImport_AddModule will crash if that is the case - since that seems to
- // only happen
- // when destroying the SBDebugger, we can make do without clearing up stdout
- // and stderr
+ // checking that we have a valid thread state - since we use our own
+ // threading and locking in some (rare) cases during cleanup Python may end
+ // up believing we have no thread state and PyImport_AddModule will crash if
+ // that is the case - since that seems to only happen when destroying the
+ // SBDebugger, we can make do without clearing up stdout and stderr
// rdar://problem/11292882
// When the current thread state is NULL, PyThreadState_Get() issues a fatal
@@ -526,8 +583,7 @@ bool ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name,
bool ScriptInterpreterPython::EnterSession(uint16_t on_entry_flags, FILE *in,
FILE *out, FILE *err) {
// If we have already entered the session, without having officially 'left'
- // it, then there is no need to
- // 'enter' it again.
+ // it, then there is no need to 'enter' it again.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
if (m_session_is_active) {
if (log)
@@ -560,8 +616,8 @@ bool ScriptInterpreterPython::EnterSession(uint16_t on_entry_flags, FILE *in,
run_string.PutCString("; lldb.frame = lldb.thread.GetSelectedFrame ()");
run_string.PutCString("')");
} else {
- // If we aren't initing the globals, we should still always set the debugger
- // (since that is always unique.)
+ // If we aren't initing the globals, we should still always set the
+ // debugger (since that is always unique.)
run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
m_dictionary_name.c_str(),
GetCommandInterpreter().GetDebugger().GetID());
@@ -695,19 +751,20 @@ static void ReadThreadBytesReceived(void *baton, const void *src,
}
bool ScriptInterpreterPython::ExecuteOneLine(
- const char *command, CommandReturnObject *result,
+ llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options) {
+ std::string command_str = command.str();
+
if (!m_valid_session)
return false;
- if (command && command[0]) {
+ if (!command.empty()) {
// We want to call run_one_line, passing in the dictionary and the command
- // string. We cannot do this through
- // PyRun_SimpleString here because the command string may contain escaped
- // characters, and putting it inside
+ // string. We cannot do this through PyRun_SimpleString here because the
+ // command string may contain escaped characters, and putting it inside
// another string to pass to PyRun_SimpleString messes up the escaping. So
- // we use the following more complicated
- // method to pass the command string directly down to Python.
+ // we use the following more complicated method to pass the command string
+ // directly down to Python.
Debugger &debugger = m_interpreter.GetDebugger();
StreamFileSP input_file_sp;
@@ -773,17 +830,14 @@ bool ScriptInterpreterPython::ExecuteOneLine(
FILE *err_file = error_file_sp->GetFile().GetStream();
bool success = false;
{
- // WARNING! It's imperative that this RAII scope be as tight as possible.
- // In particular, the
- // scope must end *before* we try to join the read thread. The reason for
- // this is that a
- // pre-requisite for joining the read thread is that we close the write
- // handle (to break the
- // pipe and cause it to wake up and exit). But acquiring the GIL as below
- // will redirect Python's
- // stdio to use this same handle. If we close the handle while Python is
- // still using it, bad
- // things will happen.
+ // WARNING! It's imperative that this RAII scope be as tight as
+ // possible. In particular, the scope must end *before* we try to join
+ // the read thread. The reason for this is that a pre-requisite for
+ // joining the read thread is that we close the write handle (to break
+ // the pipe and cause it to wake up and exit). But acquiring the GIL as
+ // below will redirect Python's stdio to use this same handle. If we
+ // close the handle while Python is still using it, bad things will
+ // happen.
Locker locker(
this,
ScriptInterpreterPython::Locker::AcquireLock |
@@ -803,7 +857,7 @@ bool ScriptInterpreterPython::ExecuteOneLine(
if (PyCallable_Check(m_run_one_line_function.get())) {
PythonObject pargs(
PyRefType::Owned,
- Py_BuildValue("(Os)", session_dict.get(), command));
+ Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));
if (pargs.IsValid()) {
PythonObject return_value(
PyRefType::Owned,
@@ -827,12 +881,12 @@ bool ScriptInterpreterPython::ExecuteOneLine(
}
if (join_read_thread) {
- // Close the write end of the pipe since we are done with our
- // one line script. This should cause the read thread that
- // output_comm is using to exit
+ // Close the write end of the pipe since we are done with our one line
+ // script. This should cause the read thread that output_comm is using to
+ // exit
output_file_sp->GetFile().Close();
- // The close above should cause this thread to exit when it gets
- // to the end of file, so let it get all its data
+ // The close above should cause this thread to exit when it gets to the
+ // end of file, so let it get all its data
output_comm.JoinReadThread();
// Now we can close the read end of the pipe
output_comm.Disconnect();
@@ -842,9 +896,10 @@ bool ScriptInterpreterPython::ExecuteOneLine(
return true;
// The one-liner failed. Append the error message.
- if (result)
+ if (result) {
result->AppendErrorWithFormat(
- "python failed attempting to evaluate '%s'\n", command);
+ "python failed attempting to evaluate '%s'\n", command_str.c_str());
+ }
return false;
}
@@ -889,21 +944,18 @@ public:
ScriptInterpreterPython::Locker::FreeAcquiredLock |
ScriptInterpreterPython::Locker::TearDownSession);
- // The following call drops into the embedded interpreter loop and stays
- // there until the
- // user chooses to exit from the Python interpreter.
- // This embedded interpreter will, as any Python code that performs I/O,
- // unlock the GIL before
- // a system call that can hang, and lock it when the syscall has
- // returned.
+ // The following call drops into the embedded interpreter loop and
+ // stays there until the user chooses to exit from the Python
+ // interpreter. This embedded interpreter will, as any Python code that
+ // performs I/O, unlock the GIL before a system call that can hang, and
+ // lock it when the syscall has returned.
// We need to surround the call to the embedded interpreter with calls
- // to PyGILState_Ensure and
- // PyGILState_Release (using the Locker above). This is because Python
- // has a global lock which must be held whenever we want
- // to touch any Python objects. Otherwise, if the user calls Python
- // code, the interpreter state will be off,
- // and things could hang (it's happened before).
+ // to PyGILState_Ensure and PyGILState_Release (using the Locker
+ // above). This is because Python has a global lock which must be held
+ // whenever we want to touch any Python objects. Otherwise, if the user
+ // calls Python code, the interpreter state will be off, and things
+ // could hang (it's happened before).
StreamString run_string;
run_string.Printf("run_python_interpreter (%s)",
@@ -934,12 +986,10 @@ void ScriptInterpreterPython::ExecuteInterpreterLoop() {
Debugger &debugger = GetCommandInterpreter().GetDebugger();
// At the moment, the only time the debugger does not have an input file
- // handle is when this is called
- // directly from Python, in which case it is both dangerous and unnecessary
- // (not to mention confusing) to
- // try to embed a running interpreter loop inside the already running Python
- // interpreter loop, so we won't
- // do it.
+ // handle is when this is called directly from Python, in which case it is
+ // both dangerous and unnecessary (not to mention confusing) to try to embed
+ // a running interpreter loop inside the already running Python interpreter
+ // loop, so we won't do it.
if (!debugger.GetInputFile()->GetFile().IsValid())
return;
@@ -974,7 +1024,7 @@ bool ScriptInterpreterPython::Interrupt() {
return false;
}
bool ScriptInterpreterPython::ExecuteOneLineWithReturn(
- const char *in_string, ScriptInterpreter::ScriptReturnType return_type,
+ llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
void *ret_value, const ExecuteScriptOptions &options) {
Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock |
@@ -1009,116 +1059,111 @@ bool ScriptInterpreterPython::ExecuteOneLineWithReturn(
if (py_error.IsValid())
PyErr_Clear();
- if (in_string != nullptr) {
- { // scope for PythonInputReaderManager
- // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
- py_return.Reset(
- PyRefType::Owned,
- PyRun_String(in_string, Py_eval_input, globals.get(), locals.get()));
- if (!py_return.IsValid()) {
- py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
- if (py_error.IsValid())
- PyErr_Clear();
-
- py_return.Reset(PyRefType::Owned,
- PyRun_String(in_string, Py_single_input, globals.get(),
- locals.get()));
- }
+ std::string as_string = in_string.str();
+ { // scope for PythonInputReaderManager
+ // PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+ py_return.Reset(PyRefType::Owned,
+ PyRun_String(as_string.c_str(), Py_eval_input,
+ globals.get(), locals.get()));
+ if (!py_return.IsValid()) {
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ py_return.Reset(PyRefType::Owned,
+ PyRun_String(as_string.c_str(), Py_single_input,
+ globals.get(), locals.get()));
}
+ }
- if (py_return.IsValid()) {
- switch (return_type) {
- case eScriptReturnTypeCharPtr: // "char *"
- {
- const char format[3] = "s#";
- success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
- break;
- }
- case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
- // Py_None
- {
- const char format[3] = "z";
- success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
- break;
- }
- case eScriptReturnTypeBool: {
- const char format[2] = "b";
- success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
- break;
- }
- case eScriptReturnTypeShortInt: {
- const char format[2] = "h";
- success = PyArg_Parse(py_return.get(), format, (short *)ret_value);
- break;
- }
- case eScriptReturnTypeShortIntUnsigned: {
- const char format[2] = "H";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
- break;
- }
- case eScriptReturnTypeInt: {
- const char format[2] = "i";
- success = PyArg_Parse(py_return.get(), format, (int *)ret_value);
- break;
- }
- case eScriptReturnTypeIntUnsigned: {
- const char format[2] = "I";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
- break;
- }
- case eScriptReturnTypeLongInt: {
- const char format[2] = "l";
- success = PyArg_Parse(py_return.get(), format, (long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongIntUnsigned: {
- const char format[2] = "k";
- success =
- PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongLong: {
- const char format[2] = "L";
- success = PyArg_Parse(py_return.get(), format, (long long *)ret_value);
- break;
- }
- case eScriptReturnTypeLongLongUnsigned: {
- const char format[2] = "K";
- success = PyArg_Parse(py_return.get(), format,
- (unsigned long long *)ret_value);
- break;
- }
- case eScriptReturnTypeFloat: {
- const char format[2] = "f";
- success = PyArg_Parse(py_return.get(), format, (float *)ret_value);
- break;
- }
- case eScriptReturnTypeDouble: {
- const char format[2] = "d";
- success = PyArg_Parse(py_return.get(), format, (double *)ret_value);
- break;
- }
- case eScriptReturnTypeChar: {
- const char format[2] = "c";
- success = PyArg_Parse(py_return.get(), format, (char *)ret_value);
- break;
- }
- case eScriptReturnTypeOpaqueObject: {
- success = true;
- PyObject *saved_value = py_return.get();
- Py_XINCREF(saved_value);
- *((PyObject **)ret_value) = saved_value;
- break;
- }
- }
-
- if (success)
- ret_success = true;
- else
- ret_success = false;
+ if (py_return.IsValid()) {
+ switch (return_type) {
+ case eScriptReturnTypeCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ break;
+ }
+ case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return ==
+ // Py_None
+ {
+ const char format[3] = "z";
+ success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
+ break;
}
+ case eScriptReturnTypeBool: {
+ const char format[2] = "b";
+ success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortInt: {
+ const char format[2] = "h";
+ success = PyArg_Parse(py_return.get(), format, (short *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortIntUnsigned: {
+ const char format[2] = "H";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeInt: {
+ const char format[2] = "i";
+ success = PyArg_Parse(py_return.get(), format, (int *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeIntUnsigned: {
+ const char format[2] = "I";
+ success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongInt: {
+ const char format[2] = "l";
+ success = PyArg_Parse(py_return.get(), format, (long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongIntUnsigned: {
+ const char format[2] = "k";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLong: {
+ const char format[2] = "L";
+ success = PyArg_Parse(py_return.get(), format, (long long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLongUnsigned: {
+ const char format[2] = "K";
+ success =
+ PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeFloat: {
+ const char format[2] = "f";
+ success = PyArg_Parse(py_return.get(), format, (float *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeDouble: {
+ const char format[2] = "d";
+ success = PyArg_Parse(py_return.get(), format, (double *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeChar: {
+ const char format[2] = "c";
+ success = PyArg_Parse(py_return.get(), format, (char *)ret_value);
+ break;
+ }
+ case eScriptReturnTypeOpaqueObject: {
+ success = true;
+ PyObject *saved_value = py_return.get();
+ Py_XINCREF(saved_value);
+ *((PyObject **)ret_value) = saved_value;
+ break;
+ }
+ }
+
+ ret_success = success;
}
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
@@ -1174,10 +1219,8 @@ Status ScriptInterpreterPython::ExecuteMultipleLines(
if (code_object.IsValid()) {
// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it
-// takes
-// a PyObject. They are convertible (hence the function
-// PyCode_Check(PyObject*), so
-// we have to do the cast for Python 2.x
+// takes a PyObject. They are convertible (hence the function
+// PyCode_Check(PyObject*), so we have to do the cast for Python 2.x
#if PY_MAJOR_VERSION >= 3
PyObject *py_code_obj = code_object.get();
#else
@@ -1243,10 +1286,9 @@ Status ScriptInterpreterPython::SetBreakpointCommandCallback(
auto data_ap = llvm::make_unique<CommandDataPython>();
// Split the command_body_text into lines, and pass that to
- // GenerateBreakpointCommandCallbackData. That will
- // wrap the body in an auto-generated function, and return the function name
- // in script_source. That is what
- // the callback will actually invoke.
+ // GenerateBreakpointCommandCallbackData. That will wrap the body in an
+ // auto-generated function, and return the function name in script_source.
+ // That is what the callback will actually invoke.
data_ap->user_source.SplitIntoLines(command_body_text);
Status error = GenerateBreakpointCommandCallbackData(data_ap->user_source,
@@ -1268,9 +1310,8 @@ void ScriptInterpreterPython::SetWatchpointCommandCallback(
// It's necessary to set both user_source and script_source to the oneliner.
// The former is used to generate callback description (as in watchpoint
- // command list)
- // while the latter is used for Python to interpret during the actual
- // callback.
+ // command list) while the latter is used for Python to interpret during the
+ // actual callback.
data_ap->user_source.AppendString(oneliner);
data_ap->script_source.assign(oneliner);
@@ -1365,8 +1406,7 @@ bool ScriptInterpreterPython::GenerateTypeScriptFunction(
return false;
// Take what the user wrote, wrap it all up inside one big auto-generated
- // Python function, passing in the
- // ValueObject as parameter to the function.
+ // Python function, passing in the ValueObject as parameter to the function.
std::string auto_generated_function_name(
GenerateUniqueName("lldb_autogen_python_type_print_func",
@@ -1430,8 +1470,8 @@ bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input,
sstr.Printf("class %s:", auto_generated_class_name.c_str());
auto_generated_class.AppendString(sstr.GetString());
- // Wrap everything up inside the class, increasing the indentation.
- // we don't need to play any fancy indentation tricks here because there is no
+ // Wrap everything up inside the class, increasing the indentation. we don't
+ // need to play any fancy indentation tricks here because there is no
// surrounding code whose indentation we need to honor
for (int i = 0; i < num_lines; ++i) {
sstr.Clear();
@@ -1439,9 +1479,8 @@ bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input,
auto_generated_class.AppendString(sstr.GetString());
}
- // Verify that the results are valid Python.
- // (even though the method is ExportFunctionDefinitionToInterpreter, a class
- // will actually be exported)
+ // Verify that the results are valid Python. (even though the method is
+ // ExportFunctionDefinitionToInterpreter, a class will actually be exported)
// (TODO: rename that method to ExportDefinitionToInterpreter)
if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
return false;
@@ -1585,8 +1624,8 @@ StructuredData::ArraySP ScriptInterpreterPython::OSPlugin_ThreadsInfo(
// GetPythonValueFormatString provides a system independent type safe way to
// convert a variable's type into a python value format. Python value formats
-// are defined in terms of builtin C types and could change from system to
-// as the underlying typedef for uint* types, size_t, off_t and other values
+// are defined in terms of builtin C types and could change from system to as
+// the underlying typedef for uint* types, size_t, off_t and other values
// change.
template <typename T> const char *GetPythonValueFormatString(T t);
@@ -2044,8 +2083,7 @@ void ScriptInterpreterPython::Clear() {
ScriptInterpreterPython::Locker::FreeAcquiredLock);
// This may be called as part of Py_Finalize. In that case the modules are
- // destroyed in random
- // order and we can't guarantee that we can access these.
+ // destroyed in random order and we can't guarantee that we can access these.
if (Py_IsInitialized())
PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
"= None; lldb.thread = None; lldb.frame = None");
@@ -2615,9 +2653,9 @@ bool ScriptInterpreterPython::LoadScriptingModule(
// strip .py or .pyc extension
ConstString extension = target_file.GetFileNameExtension();
if (extension) {
- if (::strcmp(extension.GetCString(), "py") == 0)
+ if (llvm::StringRef(extension.GetCString()) == ".py")
basename.resize(basename.length() - 3);
- else if (::strcmp(extension.GetCString(), "pyc") == 0)
+ else if (llvm::StringRef(extension.GetCString()) == ".pyc")
basename.resize(basename.length() - 4);
}
} else {
@@ -2629,9 +2667,8 @@ bool ScriptInterpreterPython::LoadScriptingModule(
command_stream.Clear();
command_stream.Printf("sys.modules.__contains__('%s')", basename.c_str());
bool does_contain = false;
- // this call will succeed if the module was ever imported in any Debugger in
- // the lifetime of the process
- // in which this LLDB framework is living
+ // this call will succeed if the module was ever imported in any Debugger
+ // in the lifetime of the process in which this LLDB framework is living
bool was_imported_globally =
(ExecuteOneLineWithReturn(
command_stream.GetData(),
@@ -2705,8 +2742,8 @@ bool ScriptInterpreterPython::IsReservedWord(const char *word) {
llvm::StringRef word_sr(word);
- // filter out a few characters that would just confuse us
- // and that are clearly not keyword material anyway
+ // filter out a few characters that would just confuse us and that are
+ // clearly not keyword material anyway
if (word_sr.find_first_of("'\"") != llvm::StringRef::npos)
return false;
@@ -2740,7 +2777,7 @@ ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler() {
}
bool ScriptInterpreterPython::RunScriptBasedCommand(
- const char *impl_function, const char *args,
+ const char *impl_function, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
const lldb_private::ExecutionContext &exe_ctx) {
@@ -2774,9 +2811,10 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
SynchronicityHandler synch_handler(debugger_sp, synchronicity);
- ret_val =
- g_swig_call_command(impl_function, m_dictionary_name.c_str(),
- debugger_sp, args, cmd_retobj, exe_ctx_ref_sp);
+ std::string args_str = args.str();
+ ret_val = g_swig_call_command(impl_function, m_dictionary_name.c_str(),
+ debugger_sp, args_str.c_str(), cmd_retobj,
+ exe_ctx_ref_sp);
}
if (!ret_val)
@@ -2788,7 +2826,7 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
}
bool ScriptInterpreterPython::RunScriptBasedCommand(
- StructuredData::GenericSP impl_obj_sp, const char *args,
+ StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
const lldb_private::ExecutionContext &exe_ctx) {
@@ -2822,8 +2860,10 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
SynchronicityHandler synch_handler(debugger_sp, synchronicity);
+ std::string args_str = args.str();
ret_val = g_swig_call_command_object(impl_obj_sp->GetValue(), debugger_sp,
- args, cmd_retobj, exe_ctx_ref_sp);
+ args_str.c_str(), cmd_retobj,
+ exe_ctx_ref_sp);
}
if (!ret_val)
@@ -2834,9 +2874,9 @@ bool ScriptInterpreterPython::RunScriptBasedCommand(
return ret_val;
}
-// in Python, a special attribute __doc__ contains the docstring
-// for an object (function, method, class, ...) if any is defined
-// Otherwise, the attribute's value is None
+// in Python, a special attribute __doc__ contains the docstring for an object
+// (function, method, class, ...) if any is defined Otherwise, the attribute's
+// value is None
bool ScriptInterpreterPython::GetDocumentationForItem(const char *item,
std::string &dest) {
dest.clear();
@@ -3106,10 +3146,9 @@ void ScriptInterpreterPython::InitializePrivate() {
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
// RAII-based initialization which correctly handles multiple-initialization,
- // version-
- // specific differences among Python 2 and Python 3, and saving and restoring
- // various
- // other pieces of state that can get mucked with during initialization.
+ // version- specific differences among Python 2 and Python 3, and saving and
+ // restoring various other pieces of state that can get mucked with during
+ // initialization.
InitializePythonRAII initialize_guard;
if (g_swig_init_callback)
@@ -3121,17 +3160,13 @@ void ScriptInterpreterPython::InitializePrivate() {
PyRun_SimpleString("import sys");
AddToSysPath(AddLocation::End, ".");
- FileSpec file_spec;
// Don't denormalize paths when calling file_spec.GetPath(). On platforms
- // that use
- // a backslash as the path separator, this will result in executing python
- // code containing
- // paths with unescaped backslashes. But Python also accepts forward slashes,
- // so to make
- // life easier we just use that.
- if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec))
+ // that use a backslash as the path separator, this will result in executing
+ // python code containing paths with unescaped backslashes. But Python also
+ // accepts forward slashes, so to make life easier we just use that.
+ if (FileSpec file_spec = GetPythonDir())
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
- if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec))
+ if (FileSpec file_spec = HostInfo::GetShlibDir())
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
PyRun_SimpleString("sys.dont_write_bytecode = 1; import "
@@ -3157,30 +3192,20 @@ void ScriptInterpreterPython::AddToSysPath(AddLocation location,
PyRun_SimpleString(statement.c_str());
}
-// void
-// ScriptInterpreterPython::Terminate ()
-//{
-// // We are intentionally NOT calling Py_Finalize here (this would be the
-// logical place to call it). Calling
-// // Py_Finalize here causes test suite runs to seg fault: The test suite
-// runs in Python. It registers
-// // SBDebugger::Terminate to be called 'at_exit'. When the test suite
-// Python harness finishes up, it calls
-// // Py_Finalize, which calls all the 'at_exit' registered functions.
-// SBDebugger::Terminate calls Debugger::Terminate,
-// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate,
-// which calls
-// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we
-// end up with Py_Finalize being called from
-// // within Py_Finalize, which results in a seg fault.
-// //
-// // Since this function only gets called when lldb is shutting down and
-// going away anyway, the fact that we don't
-// // actually call Py_Finalize should not cause any problems (everything
-// should shut down/go away anyway when the
-// // process exits).
-// //
-//// Py_Finalize ();
-//}
-
-#endif // #ifdef LLDB_DISABLE_PYTHON
+// We are intentionally NOT calling Py_Finalize here (this would be the logical
+// place to call it). Calling Py_Finalize here causes test suite runs to seg
+// fault: The test suite runs in Python. It registers SBDebugger::Terminate to
+// be called 'at_exit'. When the test suite Python harness finishes up, it
+// calls Py_Finalize, which calls all the 'at_exit' registered functions.
+// SBDebugger::Terminate calls Debugger::Terminate, which calls lldb::Terminate,
+// which calls ScriptInterpreter::Terminate, which calls
+// ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end
+// up with Py_Finalize being called from within Py_Finalize, which results in a
+// seg fault. Since this function only gets called when lldb is shutting down
+// and going away anyway, the fact that we don't actually call Py_Finalize
+// should not cause any problems (everything should shut down/go away anyway
+// when the process exits).
+//
+// void ScriptInterpreterPython::Terminate() { Py_Finalize (); }
+
+#endif // LLDB_DISABLE_PYTHON
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index a71fcea7519c..b13979dc069b 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -151,14 +151,14 @@ public:
bool Interrupt() override;
bool ExecuteOneLine(
- const char *command, CommandReturnObject *result,
+ llvm::StringRef command, CommandReturnObject *result,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
void ExecuteInterpreterLoop() override;
bool ExecuteOneLineWithReturn(
- const char *in_string, ScriptInterpreter::ScriptReturnType return_type,
- void *ret_value,
+ llvm::StringRef in_string,
+ ScriptInterpreter::ScriptReturnType return_type, void *ret_value,
const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
lldb_private::Status ExecuteMultipleLines(
@@ -259,18 +259,17 @@ public:
GetSyntheticTypeName(const StructuredData::ObjectSP &implementor) override;
bool
- RunScriptBasedCommand(const char *impl_function, const char *args,
+ RunScriptBasedCommand(const char *impl_function, llvm::StringRef args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject &cmd_retobj,
Status &error,
const lldb_private::ExecutionContext &exe_ctx) override;
- bool
- RunScriptBasedCommand(StructuredData::GenericSP impl_obj_sp, const char *args,
- ScriptedCommandSynchronicity synchronicity,
- lldb_private::CommandReturnObject &cmd_retobj,
- Status &error,
- const lldb_private::ExecutionContext &exe_ctx) override;
+ bool RunScriptBasedCommand(
+ StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj, Status &error,
+ const lldb_private::ExecutionContext &exe_ctx) override;
Status GenerateFunction(const char *signature,
const StringList &input) override;
@@ -445,6 +444,8 @@ public:
static const char *GetPluginDescriptionStatic();
+ static FileSpec GetPythonDir();
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -509,6 +510,10 @@ protected:
static void AddToSysPath(AddLocation location, std::string path);
+ static void ComputePythonDirForApple(llvm::SmallVectorImpl<char> &path);
+ static void ComputePythonDirForPosix(llvm::SmallVectorImpl<char> &path);
+ static void ComputePythonDirForWindows(llvm::SmallVectorImpl<char> &path);
+
bool EnterSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
void LeaveSession();
diff --git a/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/source/Plugins/ScriptInterpreter/Python/lldb-python.h
index ee13b7a5cd1f..f929baade2e4 100644
--- a/source/Plugins/ScriptInterpreter/Python/lldb-python.h
+++ b/source/Plugins/ScriptInterpreter/Python/lldb-python.h
@@ -1,5 +1,4 @@
-//===-- lldb-python.h --------------------------------------------*- C++
-//-*-===//
+//===-- lldb-python.h -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,7 +17,7 @@
// Python is disabled in this build
#else
#include "llvm/Support/Compiler.h"
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
// If anyone #includes Host/PosixApi.h later, it will try to typedef pid_t. We
// need to ensure this doesn't happen. At the same time, Python.h will also try
// to redefine a bunch of stuff that PosixApi.h defines. So define it all now
diff --git a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index 8424b55ee69c..e33e26507fb1 100644
--- a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -23,6 +23,7 @@
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Property.h"
@@ -184,10 +185,10 @@ const char *const s_filter_attributes[] = {
"message", // message contents, fully expanded
"subsystem" // subsystem of the log message
- // Consider impelmenting this action as it would be cheaper to filter.
- // "message" requires always formatting the message, which is a waste
- // of cycles if it ends up being rejected.
- // "format", // format string used to format message text
+ // Consider implementing this action as it would be cheaper to filter.
+ // "message" requires always formatting the message, which is a waste of
+ // cycles if it ends up being rejected. "format", // format string
+ // used to format message text
};
static const ConstString &GetDarwinLogTypeName() {
@@ -238,11 +239,10 @@ public:
// Indicate whether this is an accept or reject rule.
dict_p->AddBooleanItem("accept", m_accept);
- // Indicate which attribute of the message this filter references.
- // This can drop into the rule-specific DoSerialization if we get
- // to the point where not all FilterRule derived classes work on
- // an attribute. (e.g. logical and/or and other compound
- // operations).
+ // Indicate which attribute of the message this filter references. This can
+ // drop into the rule-specific DoSerialization if we get to the point where
+ // not all FilterRule derived classes work on an attribute. (e.g. logical
+ // and/or and other compound operations).
dict_p->AddStringItem("attribute", s_filter_attributes[m_attribute_index]);
// Indicate the type of the rule.
@@ -403,9 +403,9 @@ static void RegisterFilterOperations() {
// -------------------------------------------------------------------------
static OptionDefinition g_enable_option_table[] = {
- // Source stream include/exclude options (the first-level filter).
- // This one should be made as small as possible as everything that
- // goes through here must be processed by the process monitor.
+ // Source stream include/exclude options (the first-level filter). This one
+ // should be made as small as possible as everything that goes through here
+ // must be processed by the process monitor.
{LLDB_OPT_SET_ALL, false, "any-process", 'a', OptionParser::eNoArgument,
nullptr, nullptr, 0, eArgTypeNone,
"Specifies log messages from other related processes should be "
@@ -419,10 +419,10 @@ static OptionDefinition g_enable_option_table[] = {
"Specifies info-level log messages should be included."},
{LLDB_OPT_SET_ALL, false, "filter", 'f', OptionParser::eRequiredArgument,
nullptr, nullptr, 0, eArgRawInput,
- // There doesn't appear to be a great way for me to have these
- // multi-line, formatted tables in help. This looks mostly right
- // but there are extra linefeeds added at seemingly random spots,
- // and indentation isn't handled properly on those lines.
+ // There doesn't appear to be a great way for me to have these multi-line,
+ // formatted tables in help. This looks mostly right but there are extra
+ // linefeeds added at seemingly random spots, and indentation isn't
+ // handled properly on those lines.
"Appends a filter rule to the log message filter chain. Multiple "
"rules may be added by specifying this option multiple times, "
"once per filter rule. Filter rules are processed in the order "
@@ -488,11 +488,11 @@ static OptionDefinition g_enable_option_table[] = {
"a log message."},
{LLDB_OPT_SET_ALL, false, "category", 'c', OptionParser::eNoArgument,
nullptr, nullptr, 0, eArgTypeNone,
- "Include the category in the the message header when displaying "
+ "Include the category in the message header when displaying "
"a log message."},
{LLDB_OPT_SET_ALL, false, "activity-chain", 'C', OptionParser::eNoArgument,
nullptr, nullptr, 0, eArgTypeNone,
- "Include the activity parent-child chain in the the message header "
+ "Include the activity parent-child chain in the message header "
"when displaying a log message. The activity hierarchy is "
"displayed as {grandparent-activity}:"
"{parent-activity}:{activity}[:...]."},
@@ -544,7 +544,8 @@ public:
break;
case 'b':
- m_broadcast_events = Args::StringToBoolean(option_arg, true, nullptr);
+ m_broadcast_events =
+ OptionArgParser::ToBoolean(option_arg, true, nullptr);
break;
case 'c':
@@ -560,7 +561,7 @@ public:
break;
case 'e':
- m_echo_to_stderr = Args::StringToBoolean(option_arg, false, nullptr);
+ m_echo_to_stderr = OptionArgParser::ToBoolean(option_arg, false, nullptr);
break;
case 'f':
@@ -571,12 +572,12 @@ public:
break;
case 'l':
- m_live_stream = Args::StringToBoolean(option_arg, false, nullptr);
+ m_live_stream = OptionArgParser::ToBoolean(option_arg, false, nullptr);
break;
case 'n':
m_filter_fall_through_accepts =
- Args::StringToBoolean(option_arg, true, nullptr);
+ OptionArgParser::ToBoolean(option_arg, true, nullptr);
break;
case 'r':
@@ -614,7 +615,7 @@ public:
source_flags_sp->AddBooleanItem("any-process", m_include_any_process);
source_flags_sp->AddBooleanItem("debug-level", m_include_debug_level);
- // The debug-level flag, if set, implies info-level.
+ // The debug-level flag, if set, implies info-level.
source_flags_sp->AddBooleanItem("info-level", m_include_info_level ||
m_include_debug_level);
source_flags_sp->AddBooleanItem("live-stream", m_live_stream);
@@ -784,12 +785,11 @@ protected:
if (!source_name)
return;
- // Check if we're *not* using strict sources. If not,
- // then the user is going to get debug-level info
- // anyways, probably not what they're expecting.
- // Unfortunately we can only fix this by adding an
- // env var, which would have had to have happened
- // already. Thus, a warning is the best we can do here.
+ // Check if we're *not* using strict sources. If not, then the user is
+ // going to get debug-level info anyways, probably not what they're
+ // expecting. Unfortunately we can only fix this by adding an env var,
+ // which would have had to have happened already. Thus, a warning is the
+ // best we can do here.
StreamString stream;
stream.Printf("darwin-log source settings specify to exclude "
"%s messages, but setting "
@@ -803,24 +803,22 @@ protected:
}
bool DoExecute(Args &command, CommandReturnObject &result) override {
- // First off, set the global sticky state of enable/disable
- // based on this command execution.
+ // First off, set the global sticky state of enable/disable based on this
+ // command execution.
s_is_explicitly_enabled = m_enable;
- // Next, if this is an enable, save off the option data.
- // We will need it later if a process hasn't been launched or
- // attached yet.
+ // Next, if this is an enable, save off the option data. We will need it
+ // later if a process hasn't been launched or attached yet.
if (m_enable) {
- // Save off enabled configuration so we can apply these parsed
- // options the next time an attach or launch occurs.
+ // Save off enabled configuration so we can apply these parsed options
+ // the next time an attach or launch occurs.
DebuggerSP debugger_sp =
GetCommandInterpreter().GetDebugger().shared_from_this();
SetGlobalEnableOptions(debugger_sp, m_options_sp);
}
- // Now check if we have a running process. If so, we should
- // instruct the process monitor to enable/disable DarwinLog support
- // now.
+ // Now check if we have a running process. If so, we should instruct the
+ // process monitor to enable/disable DarwinLog support now.
Target *target = GetSelectedOrDummyTarget();
if (!target) {
// No target, so there is nothing more to do right now.
@@ -831,14 +829,13 @@ protected:
// Grab the active process.
auto process_sp = target->GetProcessSP();
if (!process_sp) {
- // No active process, so there is nothing more to do right
- // now.
+ // No active process, so there is nothing more to do right now.
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return true;
}
- // If the process is no longer alive, we can't do this now.
- // We'll catch it the next time the process is started up.
+ // If the process is no longer alive, we can't do this now. We'll catch it
+ // the next time the process is started up.
if (!process_sp->IsAlive()) {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
return true;
@@ -857,19 +854,17 @@ protected:
*static_cast<StructuredDataDarwinLog *>(plugin_sp.get());
if (m_enable) {
- // Hook up the breakpoint for the process that detects when
- // libtrace has been sufficiently initialized to really start
- // the os_log stream. This is insurance to assure us that
- // logging is really enabled. Requesting that logging be
- // enabled for a process before libtrace is initialized
- // results in a scenario where no errors occur, but no logging
- // is captured, either. This step is to eliminate that
- // possibility.
+ // Hook up the breakpoint for the process that detects when libtrace has
+ // been sufficiently initialized to really start the os_log stream. This
+ // is insurance to assure us that logging is really enabled. Requesting
+ // that logging be enabled for a process before libtrace is initialized
+ // results in a scenario where no errors occur, but no logging is
+ // captured, either. This step is to eliminate that possibility.
plugin.AddInitCompletionHook(*process_sp.get());
}
- // Send configuration to the feature by way of the process.
- // Construct the options we will use.
+ // Send configuration to the feature by way of the process. Construct the
+ // options we will use.
auto config_sp = m_options_sp->BuildConfigurationData(m_enable);
const Status error =
process_sp->ConfigureStructuredData(GetDarwinLogTypeName(), config_sp);
@@ -882,8 +877,8 @@ protected:
plugin.SetEnabled(false);
} else {
result.SetStatus(eReturnStatusSuccessFinishNoResult);
- // Our configuration succeeeded, so we're enabled/disabled
- // per whichever one this command is setup to do.
+ // Our configuration succeeded, so we're enabled/disabled per whichever
+ // one this command is setup to do.
plugin.SetEnabled(m_enable);
}
return result.Succeeded();
@@ -914,8 +909,8 @@ protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
auto &stream = result.GetOutputStream();
- // Figure out if we've got a process. If so, we can tell if
- // DarwinLog is available for that process.
+ // Figure out if we've got a process. If so, we can tell if DarwinLog is
+ // available for that process.
Target *target = GetSelectedOrDummyTarget();
auto process_sp = target ? target->GetProcessSP() : ProcessSP();
if (!target || !process_sp) {
@@ -1013,13 +1008,13 @@ public:
};
EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
- // We are abusing the options data model here so that we can parse
- // options without requiring the Debugger instance.
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS);
+ // We are abusing the options data model here so that we can parse options
+ // without requiring the Debugger instance.
- // We have an empty execution context at this point. We only want
- // to parse options, and we don't need any context to do this here.
- // In fact, we want to be able to parse the enable options before having
- // any context.
+ // We have an empty execution context at this point. We only want to parse
+ // options, and we don't need any context to do this here. In fact, we want
+ // to be able to parse the enable options before having any context.
ExecutionContext exe_ctx;
EnableOptionsSP options_sp(new EnableOptions());
@@ -1044,22 +1039,23 @@ EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
options_property_sp->GetAsString()->GetCurrentValue();
Args args(enable_options);
if (args.GetArgumentCount() > 0) {
- // Eliminate the initial '--' that would be required to set the
- // settings that themselves include '-' and/or '--'.
+ // Eliminate the initial '--' that would be required to set the settings
+ // that themselves include '-' and/or '--'.
const char *first_arg = args.GetArgumentAtIndex(0);
if (first_arg && (strcmp(first_arg, "--") == 0))
args.Shift();
}
- // ParseOptions calls getopt_long_only, which always skips the zero'th item in
- // the array and starts at position 1,
- // so we need to push a dummy value into position zero.
- args.Unshift(llvm::StringRef("dummy_string"));
bool require_validation = false;
- error = args.ParseOptions(*options_sp.get(), &exe_ctx, PlatformSP(),
- require_validation);
- if (!error.Success())
+ llvm::Expected<Args> args_or =
+ options_sp->Parse(args, &exe_ctx, PlatformSP(), require_validation);
+ if (!args_or) {
+ LLDB_LOG_ERROR(
+ log, args_or.takeError(),
+ "Parsing plugin.structured-data.darwin-log.auto-enable-options value "
+ "failed: {0}");
return EnableOptionsSP();
+ }
if (!options_sp->VerifyOptions(result))
return EnableOptionsSP();
@@ -1168,9 +1164,9 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData(
return;
}
- // Broadcast the structured data event if we have that enabled.
- // This is the way that the outside world (all clients) get access
- // to this data. This plugin sets policy as to whether we do that.
+ // Broadcast the structured data event if we have that enabled. This is the
+ // way that the outside world (all clients) get access to this data. This
+ // plugin sets policy as to whether we do that.
DebuggerSP debugger_sp = process.GetTarget().GetDebugger().shared_from_this();
auto options_sp = GetGlobalEnableOptions(debugger_sp);
if (options_sp && options_sp->GetBroadcastEvents()) {
@@ -1180,8 +1176,8 @@ void StructuredDataDarwinLog::HandleArrivalOfStructuredData(
process.BroadcastStructuredData(object_sp, shared_from_this());
}
- // Later, hang on to a configurable amount of these and allow commands
- // to inspect, including showing backtraces.
+ // Later, hang on to a configurable amount of these and allow commands to
+ // inspect, including showing backtraces.
}
static void SetErrorWithJSON(Status &error, const char *message,
@@ -1257,8 +1253,8 @@ Status StructuredDataDarwinLog::GetDescription(
return false;
}
- // If we haven't already grabbed the first timestamp
- // value, do that now.
+ // If we haven't already grabbed the first timestamp value, do that
+ // now.
if (!m_recorded_first_timestamp) {
uint64_t timestamp = 0;
if (event->GetValueForKeyAsInteger("timestamp", timestamp)) {
@@ -1296,8 +1292,8 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
// Check if we should enable the darwin log support on startup/attach.
if (!GetGlobalProperties()->GetEnableOnStartup() &&
!s_is_explicitly_enabled) {
- // We're neither auto-enabled or explicitly enabled, so we shouldn't
- // try to enable here.
+ // We're neither auto-enabled or explicitly enabled, so we shouldn't try to
+ // enable here.
if (log)
log->Printf("StructuredDataDarwinLog::%s not applicable, we're not "
"enabled (process uid %u)",
@@ -1317,9 +1313,9 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
}
}
- // The logging support module name, specifies the name of
- // the image name that must be loaded into the debugged process before
- // we can try to enable logging.
+ // The logging support module name, specifies the name of the image name that
+ // must be loaded into the debugged process before we can try to enable
+ // logging.
const char *logging_module_cstr =
GetGlobalProperties()->GetLoggingModuleName();
if (!logging_module_cstr || (logging_module_cstr[0] == 0)) {
@@ -1359,8 +1355,8 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
return;
}
- // Time to enqueue the breakpoint so we can wait for logging support
- // to be initialized before we try to tap the libtrace stream.
+ // Time to enqueue the breakpoint so we can wait for logging support to be
+ // initialized before we try to tap the libtrace stream.
AddInitCompletionHook(process);
if (log)
log->Printf("StructuredDataDarwinLog::%s post-init hook breakpoint "
@@ -1368,13 +1364,13 @@ void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
__FUNCTION__, logging_module_name.AsCString(),
process.GetUniqueID());
- // We need to try the enable here as well, which will succeed
- // in the event that we're attaching to (rather than launching) the
- // process and the process is already past initialization time. In that
- // case, the completion breakpoint will never get hit and therefore won't
- // start that way. It doesn't hurt much beyond a bit of bandwidth
- // if we end up doing this twice. It hurts much more if we don't get
- // the logging enabled when the user expects it.
+ // We need to try the enable here as well, which will succeed in the event
+ // that we're attaching to (rather than launching) the process and the
+ // process is already past initialization time. In that case, the completion
+ // breakpoint will never get hit and therefore won't start that way. It
+ // doesn't hurt much beyond a bit of bandwidth if we end up doing this twice.
+ // It hurts much more if we don't get the logging enabled when the user
+ // expects it.
EnableNow();
}
@@ -1411,8 +1407,7 @@ StructuredDataDarwinLog::StructuredDataDarwinLog(const ProcessWP &process_wp)
StructuredDataPluginSP
StructuredDataDarwinLog::CreateInstance(Process &process) {
- // Currently only Apple targets support the os_log/os_activity
- // protocol.
+ // Currently only Apple targets support the os_log/os_activity protocol.
if (process.GetTarget().GetArchitecture().GetTriple().getVendor() ==
llvm::Triple::VendorType::Apple) {
auto process_wp = ProcessWP(process.shared_from_this());
@@ -1459,20 +1454,20 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
Target *target) {
Status error;
- // If we're not debugging this launched process, there's nothing for us
- // to do here.
+ // If we're not debugging this launched process, there's nothing for us to do
+ // here.
if (!launch_info.GetFlags().AnySet(eLaunchFlagDebug))
return error;
// Darwin os_log() support automatically adds debug-level and info-level
// messages when a debugger is attached to a process. However, with
- // integrated suppport for debugging built into the command-line LLDB,
- // the user may specifically set to *not* include debug-level and info-level
- // content. When the user is using the integrated log support, we want
- // to put the kabosh on that automatic adding of info and debug level.
- // This is done by adding an environment variable to the process on launch.
- // (This also means it is not possible to suppress this behavior if
- // attaching to an already-running app).
+ // integrated support for debugging built into the command-line LLDB, the
+ // user may specifically set to *not* include debug-level and info-level
+ // content. When the user is using the integrated log support, we want to
+ // put the kabosh on that automatic adding of info and debug level. This is
+ // done by adding an environment variable to the process on launch. (This
+ // also means it is not possible to suppress this behavior if attaching to an
+ // already-running app).
// Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
// If the target architecture is not one that supports DarwinLog, we have
@@ -1483,20 +1478,19 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
return error;
}
- // If DarwinLog is not enabled (either by explicit user command or via
- // the auto-enable option), then we have nothing to do.
+ // If DarwinLog is not enabled (either by explicit user command or via the
+ // auto-enable option), then we have nothing to do.
if (!GetGlobalProperties()->GetEnableOnStartup() &&
!s_is_explicitly_enabled) {
// Nothing to do, DarwinLog is not enabled.
return error;
}
- // If we don't have parsed configuration info, that implies we have
- // enable-on-startup set up, but we haven't yet attempted to run the
- // enable command.
+ // If we don't have parsed configuration info, that implies we have enable-
+ // on-startup set up, but we haven't yet attempted to run the enable command.
if (!target) {
- // We really can't do this without a target. We need to be able
- // to get to the debugger to get the proper options to do this right.
+ // We really can't do this without a target. We need to be able to get to
+ // the debugger to get the proper options to do this right.
// TODO log.
error.SetErrorString("requires a target to auto-enable DarwinLog.");
return error;
@@ -1509,34 +1503,28 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
if (!options_sp || !error.Success())
return error;
- // We already parsed the options, save them now so we don't generate
- // them again until the user runs the command manually.
+ // We already parsed the options, save them now so we don't generate them
+ // again until the user runs the command manually.
SetGlobalEnableOptions(debugger_sp, options_sp);
}
- auto &env_vars = launch_info.GetEnvironmentEntries();
if (!options_sp->GetEchoToStdErr()) {
- // The user doesn't want to see os_log/NSLog messages echo to stderr.
- // That mechanism is entirely separate from the DarwinLog support.
- // By default we don't want to get it via stderr, because that would
- // be in duplicate of the explicit log support here.
+ // The user doesn't want to see os_log/NSLog messages echo to stderr. That
+ // mechanism is entirely separate from the DarwinLog support. By default we
+ // don't want to get it via stderr, because that would be in duplicate of
+ // the explicit log support here.
// Here we need to strip out any OS_ACTIVITY_DT_MODE setting to prevent
// echoing of os_log()/NSLog() to stderr in the target program.
- size_t argument_index;
- if (env_vars.ContainsEnvironmentVariable(
- llvm::StringRef("OS_ACTIVITY_DT_MODE"), &argument_index))
- env_vars.DeleteArgumentAtIndex(argument_index);
+ launch_info.GetEnvironment().erase("OS_ACTIVITY_DT_MODE");
- // We will also set the env var that tells any downstream launcher
- // from adding OS_ACTIVITY_DT_MODE.
- env_vars.AddOrReplaceEnvironmentVariable(
- llvm::StringRef("IDE_DISABLED_OS_ACTIVITY_DT_MODE"),
- llvm::StringRef("1"));
+ // We will also set the env var that tells any downstream launcher from
+ // adding OS_ACTIVITY_DT_MODE.
+ launch_info.GetEnvironment()["IDE_DISABLED_OS_ACTIVITY_DT_MODE"] = "1";
}
- // Set the OS_ACTIVITY_MODE env var appropriately to enable/disable
- // debug and info level messages.
+ // Set the OS_ACTIVITY_MODE env var appropriately to enable/disable debug and
+ // info level messages.
const char *env_var_value;
if (options_sp->GetIncludeDebugLevel())
env_var_value = "debug";
@@ -1545,10 +1533,7 @@ Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
else
env_var_value = "default";
- if (env_var_value) {
- launch_info.GetEnvironmentEntries().AddOrReplaceEnvironmentVariable(
- llvm::StringRef("OS_ACTIVITY_MODE"), llvm::StringRef(env_var_value));
- }
+ launch_info.GetEnvironment()["OS_ACTIVITY_MODE"] = env_var_value;
return error;
}
@@ -1558,8 +1543,8 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback(
lldb::user_id_t break_loc_id) {
// We hit the init function. We now want to enqueue our new thread plan,
// which will in turn enqueue a StepOut thread plan. When the StepOut
- // finishes and control returns to our new thread plan, that is the time
- // when we can execute our logic to enable the logging support.
+ // finishes and control returns to our new thread plan, that is the time when
+ // we can execute our logic to enable the logging support.
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
if (log)
@@ -1618,8 +1603,8 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback(
process_uid);
return;
}
- // Make sure we only call it once, just in case the
- // thread plan hits the breakpoint twice.
+ // Make sure we only call it once, just in case the thread plan hits
+ // the breakpoint twice.
if (!called_enable_method) {
if (log)
log->Printf("StructuredDataDarwinLog::post-init callback: "
@@ -1629,8 +1614,8 @@ bool StructuredDataDarwinLog::InitCompletionHookCallback(
->EnableNow();
called_enable_method = true;
} else {
- // Our breakpoint was hit more than once. Unexpected but
- // no harm done. Log it.
+ // Our breakpoint was hit more than once. Unexpected but no harm
+ // done. Log it.
if (log)
log->Printf("StructuredDataDarwinLog::post-init callback: "
"skipping EnableNow(), already called by "
@@ -1687,8 +1672,8 @@ void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) {
m_added_breakpoint = true;
}
- // Set a breakpoint for the process that will kick in when libtrace
- // has finished its initialization.
+ // Set a breakpoint for the process that will kick in when libtrace has
+ // finished its initialization.
Target &target = process.GetTarget();
// Build up the module list.
@@ -1793,8 +1778,8 @@ StructuredDataDarwinLog::DumpHeader(Stream &output_stream,
if (header_count > 0)
stream.PutChar(',');
- // Display the activity chain, from parent-most to child-most
- // activity, separated by a colon (:).
+ // Display the activity chain, from parent-most to child-most activity,
+ // separated by a colon (:).
stream.PutCString("activity-chain=");
stream.PutCString(activity_chain);
++header_count;
@@ -1836,8 +1821,8 @@ size_t StructuredDataDarwinLog::HandleDisplayOfEvent(
// Check the type of the event.
ConstString event_type;
if (!event.GetValueForKeyAsString("type", event_type)) {
- // Hmm, we expected to get events that describe
- // what they are. Continue anyway.
+ // Hmm, we expected to get events that describe what they are. Continue
+ // anyway.
return 0;
}
@@ -1885,10 +1870,10 @@ void StructuredDataDarwinLog::EnableNow() {
log->Printf("StructuredDataDarwinLog::%s() call is for process uid %u",
__FUNCTION__, process_sp->GetUniqueID());
- // If we have configuration data, we can directly enable it now.
- // Otherwise, we need to run through the command interpreter to parse
- // the auto-run options (which is the only way we get here without having
- // already-parsed configuration data).
+ // If we have configuration data, we can directly enable it now. Otherwise,
+ // we need to run through the command interpreter to parse the auto-run
+ // options (which is the only way we get here without having already-parsed
+ // configuration data).
DebuggerSP debugger_sp =
process_sp->GetTarget().GetDebugger().shared_from_this();
if (!debugger_sp) {
@@ -1901,8 +1886,8 @@ void StructuredDataDarwinLog::EnableNow() {
auto options_sp = GetGlobalEnableOptions(debugger_sp);
if (!options_sp) {
- // We haven't run the enable command yet. Just do that now, it'll
- // take care of the rest.
+ // We haven't run the enable command yet. Just do that now, it'll take
+ // care of the rest.
auto &interpreter = debugger_sp->GetCommandInterpreter();
const bool success = RunEnableCommand(interpreter);
if (log) {
@@ -1925,8 +1910,8 @@ void StructuredDataDarwinLog::EnableNow() {
return;
}
- // We've previously been enabled. We will re-enable now with the
- // previously specified options.
+ // We've previously been enabled. We will re-enable now with the previously
+ // specified options.
auto config_sp = options_sp->BuildConfigurationData(true);
if (!config_sp) {
if (log)
diff --git a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
new file mode 100644
index 000000000000..db75cf9c3bb3
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp
@@ -0,0 +1,177 @@
+//===-- AppleDWARFIndex.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
+#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/Function.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create(
+ Module &module, DWARFDataExtractor apple_names,
+ DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
+ DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) {
+ auto apple_names_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_names, debug_str, ".apple_names");
+ if (!apple_names_table_up->IsValid())
+ apple_names_table_up.reset();
+
+ auto apple_namespaces_table_up =
+ llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_namespaces, debug_str, ".apple_namespaces");
+ if (!apple_namespaces_table_up->IsValid())
+ apple_namespaces_table_up.reset();
+
+ auto apple_types_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_types, debug_str, ".apple_types");
+ if (!apple_types_table_up->IsValid())
+ apple_types_table_up.reset();
+
+ auto apple_objc_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>(
+ apple_objc, debug_str, ".apple_objc");
+ if (!apple_objc_table_up->IsValid())
+ apple_objc_table_up.reset();
+
+ if (apple_names_table_up || apple_names_table_up || apple_types_table_up ||
+ apple_objc_table_up)
+ return llvm::make_unique<AppleDWARFIndex>(
+ module, std::move(apple_names_table_up),
+ std::move(apple_namespaces_table_up), std::move(apple_types_table_up),
+ std::move(apple_objc_table_up));
+
+ return nullptr;
+}
+
+void AppleDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) {
+ if (m_apple_names_up)
+ m_apple_names_up->FindByName(basename.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) {
+ if (!m_apple_names_up)
+ return;
+
+ DWARFMappedHash::DIEInfoArray hash_data;
+ if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
+ DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
+}
+
+void AppleDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
+ DIEArray &offsets) {
+ if (!m_apple_names_up)
+ return;
+
+ DWARFMappedHash::DIEInfoArray hash_data;
+ if (m_apple_names_up->AppendAllDIEsInRange(
+ cu.GetOffset(), cu.GetNextCompileUnitOffset(), hash_data))
+ DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
+}
+
+void AppleDWARFIndex::GetObjCMethods(ConstString class_name,
+ DIEArray &offsets) {
+ if (m_apple_objc_up)
+ m_apple_objc_up->FindByName(class_name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) {
+ if (m_apple_types_up) {
+ m_apple_types_up->FindCompleteObjCClassByName(
+ class_name.GetStringRef(), offsets, must_be_implementation);
+ }
+}
+
+void AppleDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
+ if (m_apple_types_up)
+ m_apple_types_up->FindByName(name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context,
+ DIEArray &offsets) {
+ if (!m_apple_types_up)
+ return;
+
+ Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS);
+ const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
+ DWARFMappedHash::eAtomTypeTag);
+ const bool has_qualified_name_hash =
+ m_apple_types_up->GetHeader().header_data.ContainsAtom(
+ DWARFMappedHash::eAtomTypeQualNameHash);
+ const ConstString type_name(context[0].name);
+ const dw_tag_t tag = context[0].tag;
+ if (has_tag && has_qualified_name_hash) {
+ const char *qualified_name = context.GetQualifiedName();
+ const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
+ if (log)
+ m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
+ m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
+ type_name.GetStringRef(), tag, qualified_name_hash, offsets);
+ } else if (has_tag) {
+ if (log)
+ m_module.LogMessage(log, "FindByNameAndTag()");
+ m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets);
+ } else
+ m_apple_types_up->FindByName(type_name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
+ if (m_apple_namespaces_up)
+ m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets);
+}
+
+void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+ DIEArray offsets;
+ m_apple_names_up->FindByName(name.GetStringRef(), offsets);
+ for (const DIERef &die_ref : offsets) {
+ ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx,
+ name_type_mask, dies);
+ }
+}
+
+void AppleDWARFIndex::GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) {
+ if (!m_apple_names_up)
+ return;
+
+ DWARFMappedHash::DIEInfoArray hash_data;
+ if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
+ DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
+}
+
+void AppleDWARFIndex::ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) {
+ m_module.ReportErrorIfModifyDetected(
+ "the DWARF debug information has been modified (accelerator table had "
+ "bad die 0x%8.8x for '%s')\n",
+ offset, name.str().c_str());
+}
+
+void AppleDWARFIndex::Dump(Stream &s) {
+ if (m_apple_names_up)
+ s.PutCString(".apple_names index present\n");
+ if (m_apple_namespaces_up)
+ s.PutCString(".apple_namespaces index present\n");
+ if (m_apple_types_up)
+ s.PutCString(".apple_types index present\n");
+ if (m_apple_objc_up)
+ s.PutCString(".apple_objc index present\n");
+ // TODO: Dump index contents
+}
diff --git a/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
new file mode 100644
index 000000000000..ea133d0e73cf
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h
@@ -0,0 +1,64 @@
+//===-- AppleDWARFIndex.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_APPLEDWARFINDEX_H
+#define LLDB_APPLEDWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/HashedNameToDIE.h"
+
+namespace lldb_private {
+class AppleDWARFIndex : public DWARFIndex {
+public:
+ static std::unique_ptr<AppleDWARFIndex>
+ Create(Module &module, DWARFDataExtractor apple_names,
+ DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
+ DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str);
+
+ AppleDWARFIndex(
+ Module &module, std::unique_ptr<DWARFMappedHash::MemoryTable> apple_names,
+ std::unique_ptr<DWARFMappedHash::MemoryTable> apple_namespaces,
+ std::unique_ptr<DWARFMappedHash::MemoryTable> apple_types,
+ std::unique_ptr<DWARFMappedHash::MemoryTable> apple_objc)
+ : DWARFIndex(module), m_apple_names_up(std::move(apple_names)),
+ m_apple_namespaces_up(std::move(apple_namespaces)),
+ m_apple_types_up(std::move(apple_types)),
+ m_apple_objc_up(std::move(apple_objc)) {}
+
+ void Preload() override {}
+
+ void GetGlobalVariables(ConstString basename, DIEArray &offsets) override;
+ void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) override;
+ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override;
+ void GetObjCMethods(ConstString class_name, DIEArray &offsets) override;
+ void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation,
+ DIEArray &offsets) override;
+ void GetTypes(ConstString name, DIEArray &offsets) override;
+ void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
+ void GetNamespaces(ConstString name, DIEArray &offsets) override;
+ void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) override;
+ void GetFunctions(const RegularExpression &regex, DIEArray &offsets) override;
+
+ void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) override;
+ void Dump(Stream &s) override;
+
+private:
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_names_up;
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_up;
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_up;
+ std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_up;
+};
+} // namespace lldb_private
+
+#endif // LLDB_APPLEDWARFINDEX_H
diff --git a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
index 05d9e6642868..f62a496f808a 100644
--- a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
+++ b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
@@ -1,4 +1,6 @@
add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
+ AppleDWARFIndex.cpp
+ DebugNamesDWARFIndex.cpp
DIERef.cpp
DWARFAbbreviationDeclaration.cpp
DWARFASTParserClang.cpp
@@ -6,6 +8,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
DWARFASTParserJava.cpp
DWARFASTParserOCaml.cpp
DWARFAttribute.cpp
+ DWARFBaseDIE.cpp
DWARFCompileUnit.cpp
DWARFDataExtractor.cpp
DWARFDebugAbbrev.cpp
@@ -17,16 +20,17 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
DWARFDebugMacro.cpp
DWARFDebugMacinfo.cpp
DWARFDebugMacinfoEntry.cpp
- DWARFDebugPubnames.cpp
- DWARFDebugPubnamesSet.cpp
DWARFDebugRanges.cpp
DWARFDeclContext.cpp
DWARFDefines.cpp
DWARFDIE.cpp
DWARFDIECollection.cpp
DWARFFormValue.cpp
+ DWARFIndex.cpp
+ DWARFUnit.cpp
HashedNameToDIE.cpp
LogChannelDWARF.cpp
+ ManualDWARFIndex.cpp
NameToDIE.cpp
SymbolFileDWARF.cpp
SymbolFileDWARFDwo.cpp
diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/source/Plugins/SymbolFile/DWARF/DIERef.cpp
index c05444c031e6..0cd0f0c0272a 100644
--- a/source/Plugins/SymbolFile/DWARF/DIERef.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DIERef.cpp
@@ -8,17 +8,12 @@
//===----------------------------------------------------------------------===//
#include "DIERef.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFFormValue.h"
#include "SymbolFileDWARF.h"
#include "SymbolFileDWARFDebugMap.h"
-DIERef::DIERef()
- : cu_offset(DW_INVALID_OFFSET), die_offset(DW_INVALID_OFFSET) {}
-
-DIERef::DIERef(dw_offset_t c, dw_offset_t d) : cu_offset(c), die_offset(d) {}
-
DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf)
: cu_offset(DW_INVALID_OFFSET), die_offset(uid & 0xffffffff) {
SymbolFileDWARFDebugMap *debug_map = dwarf->GetDebugMapSymfile();
@@ -28,7 +23,7 @@ DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf)
if (actual_dwarf) {
DWARFDebugInfo *debug_info = actual_dwarf->DebugInfo();
if (debug_info) {
- DWARFCompileUnit *dwarf_cu =
+ DWARFUnit *dwarf_cu =
debug_info->GetCompileUnitContainingDIEOffset(die_offset);
if (dwarf_cu) {
cu_offset = dwarf_cu->GetOffset();
@@ -45,7 +40,7 @@ DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf)
DIERef::DIERef(const DWARFFormValue &form_value)
: cu_offset(DW_INVALID_OFFSET), die_offset(DW_INVALID_OFFSET) {
if (form_value.IsValid()) {
- const DWARFCompileUnit *dwarf_cu = form_value.GetCompileUnit();
+ const DWARFUnit *dwarf_cu = form_value.GetCompileUnit();
if (dwarf_cu) {
if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
cu_offset = dwarf_cu->GetBaseObjOffset();
diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.h b/source/Plugins/SymbolFile/DWARF/DIERef.h
index d0048d0f6d6b..cb28c890c25a 100644
--- a/source/Plugins/SymbolFile/DWARF/DIERef.h
+++ b/source/Plugins/SymbolFile/DWARF/DIERef.h
@@ -17,9 +17,9 @@ class DWARFFormValue;
class SymbolFileDWARF;
struct DIERef {
- DIERef();
+ DIERef() = default;
- DIERef(dw_offset_t c, dw_offset_t d);
+ DIERef(dw_offset_t c, dw_offset_t d) : cu_offset(c), die_offset(d) {}
//----------------------------------------------------------------------
// In order to properly decode a lldb::user_id_t back into a DIERef we
@@ -45,8 +45,12 @@ struct DIERef {
bool operator<(const DIERef &ref) { return die_offset < ref.die_offset; }
- dw_offset_t cu_offset;
- dw_offset_t die_offset;
+ explicit operator bool() const {
+ return cu_offset != DW_INVALID_OFFSET || die_offset != DW_INVALID_OFFSET;
+ }
+
+ dw_offset_t cu_offset = DW_INVALID_OFFSET;
+ dw_offset_t die_offset = DW_INVALID_OFFSET;
};
typedef std::vector<DIERef> DIEArray;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 54b12cfb3b8c..fe6f1be3ca48 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -10,13 +10,13 @@
#include <stdlib.h>
#include "DWARFASTParserClang.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugInfo.h"
#include "DWARFDeclContext.h"
#include "DWARFDefines.h"
#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDebugMap.h"
#include "UniqueDWARFASTType.h"
@@ -24,7 +24,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangUtil.h"
@@ -39,8 +38,10 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
#include <map>
#include <vector>
@@ -105,9 +106,9 @@ struct BitfieldInfo {
bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
if (IsValid()) {
- // This bitfield info is valid, so any subsequent bitfields
- // must not overlap and must be at a higher bit offset than
- // any previous bitfield + size.
+ // This bitfield info is valid, so any subsequent bitfields must not
+ // overlap and must be at a higher bit offset than any previous bitfield
+ // + size.
return (bit_size + bit_offset) <= next_bit_offset;
} else {
// If the this BitfieldInfo is not valid, then any offset isOK
@@ -123,57 +124,108 @@ ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() {
return *m_clang_ast_importer_ap;
}
+/// Detect a forward declaration that is nested in a DW_TAG_module.
+static bool isClangModuleFwdDecl(const DWARFDIE &Die) {
+ if (!Die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
+ return false;
+ auto Parent = Die.GetParent();
+ while (Parent.IsValid()) {
+ if (Parent.Tag() == DW_TAG_module)
+ return true;
+ Parent = Parent.GetParent();
+ }
+ return false;
+}
+
TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
ModuleSP dwo_module_sp = die.GetContainingDWOModule();
- if (dwo_module_sp) {
- // This type comes from an external DWO module
- std::vector<CompilerContext> dwo_context;
- die.GetDWOContext(dwo_context);
- TypeMap dwo_types;
- if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true,
- dwo_types)) {
- const size_t num_dwo_types = dwo_types.GetSize();
- if (num_dwo_types == 1) {
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
- TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
- if (dwo_type_sp) {
- lldb_private::CompilerType dwo_type =
- dwo_type_sp->GetForwardCompilerType();
-
- lldb_private::CompilerType type =
- GetClangASTImporter().CopyType(m_ast, dwo_type);
-
- // printf ("copied_qual_type: ast = %p, clang_type = %p, name =
- // '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(),
- // external_type->GetName().GetCString());
- if (type) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- TypeSP type_sp(new Type(die.GetID(), dwarf, dwo_type_sp->GetName(),
- dwo_type_sp->GetByteSize(), NULL,
- LLDB_INVALID_UID, Type::eEncodingInvalid,
- &dwo_type_sp->GetDeclaration(), type,
- Type::eResolveStateForward));
-
- dwarf->GetTypeList()->Insert(type_sp);
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
- if (tag_decl)
- LinkDeclContextToDIE(tag_decl, die);
- else {
- clang::DeclContext *defn_decl_ctx =
- GetCachedClangDeclContextForDIE(die);
- if (defn_decl_ctx)
- LinkDeclContextToDIE(defn_decl_ctx, die);
- }
- return type_sp;
- }
- }
- }
+ if (!dwo_module_sp)
+ return TypeSP();
+
+ // This type comes from an external DWO module.
+ std::vector<CompilerContext> dwo_context;
+ die.GetDWOContext(dwo_context);
+ TypeMap dwo_types;
+
+ if (!dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true,
+ dwo_types)) {
+ if (!isClangModuleFwdDecl(die))
+ return TypeSP();
+
+ // Since this this type is defined in one of the Clang modules imported by
+ // this symbol file, search all of them.
+ auto *SymFile = die.GetCU()->GetSymbolFileDWARF();
+ for (const auto &NameModule : SymFile->getExternalTypeModules()) {
+ if (!NameModule.second)
+ continue;
+ SymbolVendor *SymVendor = NameModule.second->GetSymbolVendor();
+ if (SymVendor->FindTypes(dwo_context, true, dwo_types))
+ break;
}
}
- return TypeSP();
+
+ const size_t num_dwo_types = dwo_types.GetSize();
+ if (num_dwo_types != 1)
+ return TypeSP();
+
+ // We found a real definition for this type in the Clang module, so lets use
+ // it and cache the fact that we found a complete type for this die.
+ TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
+ if (!dwo_type_sp)
+ return TypeSP();
+
+ lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
+
+ lldb_private::CompilerType type =
+ GetClangASTImporter().CopyType(m_ast, dwo_type);
+
+ if (!type)
+ return TypeSP();
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ TypeSP type_sp(new Type(
+ die.GetID(), dwarf, dwo_type_sp->GetName(), dwo_type_sp->GetByteSize(),
+ NULL, LLDB_INVALID_UID, Type::eEncodingInvalid,
+ &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward));
+
+ dwarf->GetTypeList()->Insert(type_sp);
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
+ if (tag_decl)
+ LinkDeclContextToDIE(tag_decl, die);
+ else {
+ clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ }
+
+ return type_sp;
+}
+
+static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
+ clang::DeclContext *decl_ctx,
+ DWARFDIE die,
+ const char *type_name_cstr) {
+ auto *tag_decl_ctx = clang::dyn_cast<clang::TagDecl>(decl_ctx);
+ if (!tag_decl_ctx)
+ return;
+
+ // If this type was not imported from an external AST, there's nothing to do.
+ CompilerType type = ClangASTContext::GetTypeForDecl(tag_decl_ctx);
+ if (!type || !ast_importer.CanImport(type))
+ return;
+
+ auto qual_type = ClangUtil::GetQualType(type);
+ if (!ast_importer.RequireCompleteType(qual_type)) {
+ die.GetDWARF()->GetObjectFile()->GetModule()->ReportError(
+ "Unable to complete the Decl context for DIE '%s' at offset "
+ "0x%8.8x.\nPlease file a bug report.",
+ type_name_cstr ? type_name_cstr : "", die.GetOffset());
+ // We need to make the type look complete otherwise, we might crash in
+ // Clang when adding children.
+ if (ClangASTContext::StartTagDeclarationDefinition(type))
+ ClangASTContext::CompleteTagDeclarationDefinition(type);
+ }
}
TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
@@ -198,17 +250,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
die.GetOffset(), static_cast<void *>(context),
context_die.GetOffset(), die.GetTagAsCString(), die.GetName());
}
- //
- // Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- // if (log && dwarf_cu)
- // {
- // StreamString s;
- // die->DumpLocation (this, dwarf_cu, s);
- // dwarf->GetObjectFile()->GetModule()->LogMessage (log,
- // "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
- //
- // }
-
Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
TypeList *type_list = dwarf->GetTypeList();
if (type_ptr == NULL) {
@@ -220,6 +261,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
bool is_forward_declaration = false;
DWARFAttributes attributes;
const char *type_name_cstr = NULL;
+ const char *mangled_name_cstr = NULL;
ConstString type_name_const_str;
Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
uint64_t byte_size = 0;
@@ -268,8 +310,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_name_cstr = form_value.AsCString();
// Work around a bug in llvm-gcc where they give a name to a
- // reference type which doesn't
- // include the "&"...
+ // reference type which doesn't include the "&"...
if (tag == DW_TAG_reference_type) {
if (strchr(type_name_cstr, '&') == NULL)
type_name_cstr = NULL;
@@ -295,32 +336,32 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
if (tag == DW_TAG_typedef && encoding_uid.IsValid()) {
- // Try to parse a typedef from the DWO file first as modules
- // can contain typedef'ed structures that have no names like:
+ // Try to parse a typedef from the DWO file first as modules can
+ // contain typedef'ed structures that have no names like:
//
// typedef struct { int a; } Foo;
//
- // In this case we will have a structure with no name and a
- // typedef named "Foo" that points to this unnamed structure.
- // The name in the typedef is the only identifier for the struct,
- // so always try to get typedefs from DWO files if possible.
+ // In this case we will have a structure with no name and a typedef
+ // named "Foo" that points to this unnamed structure. The name in the
+ // typedef is the only identifier for the struct, so always try to
+ // get typedefs from DWO files if possible.
//
- // The type_sp returned will be empty if the typedef doesn't exist
- // in a DWO file, so it is cheap to call this function just to check.
+ // The type_sp returned will be empty if the typedef doesn't exist in
+ // a DWO file, so it is cheap to call this function just to check.
//
- // If we don't do this we end up creating a TypeSP that says this
- // is a typedef to type 0x123 (the DW_AT_type value would be 0x123
- // in the DW_TAG_typedef), and this is the unnamed structure type.
- // We will have a hard time tracking down an unnammed structure
- // type in the module DWO file, so we make sure we don't get into
- // this situation by always resolving typedefs from the DWO file.
+ // If we don't do this we end up creating a TypeSP that says this is
+ // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in
+ // the DW_TAG_typedef), and this is the unnamed structure type. We
+ // will have a hard time tracking down an unnammed structure type in
+ // the module DWO file, so we make sure we don't get into this
+ // situation by always resolving typedefs from the DWO file.
const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid));
- // First make sure that the die that this is typedef'ed to _is_
- // just a declaration (DW_AT_declaration == 1), not a full definition
+ // First make sure that the die that this is typedef'ed to _is_ just
+ // a declaration (DW_AT_declaration == 1), not a full definition
// since template types can't be represented in modules since only
- // concrete instances of templates are ever emitted and modules
- // won't contain those
+ // concrete instances of templates are ever emitted and modules won't
+ // contain those
if (encoding_die &&
encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) ==
1) {
@@ -433,7 +474,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective C 'id' built-in type.",
+ "is Objective-C 'id' built-in type.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
encoding_data_type = Type::eEncodingIsUID;
@@ -444,7 +485,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective C 'Class' built-in type.",
+ "is Objective-C 'Class' built-in type.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
encoding_data_type = Type::eEncodingIsUID;
@@ -454,7 +495,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective C 'selector' built-in type.",
+ "is Objective-C 'selector' built-in type.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
encoding_data_type = Type::eEncodingIsUID;
@@ -495,17 +536,6 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
&decl, clang_type, resolve_state));
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
-
- // Type* encoding_type =
- // GetUniquedTypeForDIEOffset(encoding_uid, type_sp,
- // NULL, 0, 0, false);
- // if (encoding_type != NULL)
- // {
- // if (encoding_type != DIE_IS_BEING_PARSED)
- // type_sp->SetEncodingType(encoding_type);
- // else
- // m_indirect_fixups.push_back(type_sp.get());
- // }
} break;
case DW_TAG_structure_type:
@@ -517,7 +547,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
LanguageType class_language = eLanguageTypeUnknown;
bool is_complete_objc_class = false;
- // bool struct_is_class = false;
+ size_t calling_convention
+ = llvm::dwarf::CallingConvention::DW_CC_normal;
+
const size_t num_attributes = die.GetAttributes(attributes);
if (num_attributes > 0) {
uint32_t i;
@@ -528,10 +560,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_AT_decl_file:
if (die.GetCU()->DW_AT_decl_file_attributes_are_invalid()) {
// llvm-gcc outputs invalid DW_AT_decl_file attributes that
- // always
- // point to the compile unit file, so we clear this invalid
- // value
- // so that we can still unique types efficiently.
+ // always point to the compile unit file, so we clear this
+ // invalid value so that we can still unique types
+ // efficiently.
decl.SetFile(FileSpec("<invalid>", false));
} else
decl.SetFile(
@@ -572,7 +603,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_AT_APPLE_objc_complete_type:
is_complete_objc_class = form_value.Signed();
break;
-
+ case DW_AT_calling_convention:
+ calling_convention = form_value.Unsigned();
+ break;
+
case DW_AT_allocated:
case DW_AT_associated:
case DW_AT_data_location:
@@ -587,10 +621,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
}
- // UniqueDWARFASTType is large, so don't create a local variables on the
- // stack, put it on the heap. This function is often called recursively
- // and clang isn't good and sharing the stack space for variables in
- // different blocks.
+ // UniqueDWARFASTType is large, so don't create a local variables on
+ // the stack, put it on the heap. This function is often called
+ // recursively and clang isn't good and sharing the stack space for
+ // variables in different blocks.
std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(
new UniqueDWARFASTType());
@@ -601,10 +635,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
LanguageType die_language = die.GetLanguage();
if (Language::LanguageIsCPlusPlus(die_language)) {
// For C++, we rely solely upon the one definition rule that says
- // only
- // one thing can exist at a given decl context. We ignore the file
- // and
- // line that things are declared on.
+ // only one thing can exist at a given decl context. We ignore the
+ // file and line that things are declared on.
std::string qualified_name;
if (die.GetQualifiedName(qualified_name))
unique_typename = ConstString(qualified_name);
@@ -641,17 +673,16 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (byte_size_valid && byte_size == 0 && type_name_cstr &&
die.HasChildren() == false &&
sc.comp_unit->GetLanguage() == eLanguageTypeObjC) {
- // Work around an issue with clang at the moment where
- // forward declarations for objective C classes are emitted
- // as:
+ // Work around an issue with clang at the moment where forward
+ // declarations for objective C classes are emitted as:
// DW_TAG_structure_type [2]
// DW_AT_name( "ForwardObjcClass" )
// DW_AT_byte_size( 0x00 )
// DW_AT_decl_file( "..." )
// DW_AT_decl_line( 1 )
//
- // Note that there is no DW_AT_declaration and there are
- // no children, and the byte size is zero.
+ // Note that there is no DW_AT_declaration and there are no children,
+ // and the byte size is zero.
is_forward_declaration = true;
}
@@ -659,11 +690,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
class_language == eLanguageTypeObjC_plus_plus) {
if (!is_complete_objc_class &&
die.Supports_DW_AT_APPLE_objc_complete_type()) {
- // We have a valid eSymbolTypeObjCClass class symbol whose
- // name matches the current objective C class that we
- // are trying to find and this DIE isn't the complete
- // definition (we checked is_complete_objc_class above and
- // know it is false), so the real definition is in here somewhere
+ // We have a valid eSymbolTypeObjCClass class symbol whose name
+ // matches the current objective C class that we are trying to find
+ // and this DIE isn't the complete definition (we checked
+ // is_complete_objc_class above and know it is false), so the real
+ // definition is in here somewhere
type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE(
die, type_name_const_str, true);
@@ -671,9 +702,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
SymbolFileDWARFDebugMap *debug_map_symfile =
dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
type_sp =
debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE(
die, type_name_const_str, true);
@@ -690,9 +720,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_sp->GetID());
}
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this
+ // die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
return type_sp;
}
@@ -700,11 +730,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
if (is_forward_declaration) {
- // We have a forward declaration to a type and we need
- // to try and find a full declaration. We look in the
- // current type index just in case we have a forward
- // declaration followed by an actual declarations in the
- // DWARF. If this fails, we need to look elsewhere...
+ // We have a forward declaration to a type and we need to try and
+ // find a full declaration. We look in the current type index just in
+ // case we have a forward declaration followed by an actual
+ // declarations in the DWARF. If this fails, we need to look
+ // elsewhere...
if (log) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
log, "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
@@ -730,9 +760,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
SymbolFileDWARFDebugMap *debug_map_symfile =
dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
+ // We weren't able to find a full declaration in this DWARF, see
+ // if we have a declaration anywhere else...
type_sp =
debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
die_decl_ctx);
@@ -748,9 +777,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
DW_TAG_value_to_name(tag), type_name_cstr, type_sp->GetID());
}
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(
dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID(), dwarf)));
@@ -766,9 +794,18 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (!clang_type) {
clang::DeclContext *decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
+
+ // If your decl context is a record that was imported from another
+ // AST context (in the gmodules case), we need to make sure the type
+ // backing the Decl is complete before adding children to it. This is
+ // not an issue in the non-gmodules case because the debug info will
+ // always contain a full definition of parent types in that case.
+ CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
+ type_name_cstr);
+
if (accessibility == eAccessNone && decl_ctx) {
- // Check the decl context that contains this class/struct/union.
- // If it is a class we must give it an accessibility.
+ // Check the decl context that contains this class/struct/union. If
+ // it is a class we must give it an accessibility.
const clang::Decl::Kind containing_decl_kind =
decl_ctx->getDeclKind();
if (DeclKindIsCXXClass(containing_decl_kind))
@@ -818,10 +855,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
class_language, &metadata);
}
}
-
+
// Store a forward declaration to this class type in case any
- // parameters in any class methods need it for the clang
- // types for function prototypes.
+ // parameters in any class methods need it for the clang types for
+ // function prototypes.
LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
byte_size, NULL, LLDB_INVALID_UID,
@@ -830,9 +867,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
- // Add our type to the unique type map so we don't
- // end up creating many copies of the same type over
- // and over in the ASTContext for our module
+ // Add our type to the unique type map so we don't end up creating many
+ // copies of the same type over and over in the ASTContext for our
+ // module
unique_ast_entry_ap->m_type_sp = type_sp;
unique_ast_entry_ap->m_die = die;
unique_ast_entry_ap->m_declaration = unique_decl;
@@ -844,8 +881,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
// Check to see if the DIE actually has a definition, some version of
// GCC will
// emit DIEs with DW_AT_declaration set to true, but yet still have
- // subprogram,
- // members, or inheritance, so we can't trust it
+ // subprogram, members, or inheritance, so we can't trust it
DWARFDIE child_die = die.GetFirstChild();
while (child_die) {
switch (child_die.Tag()) {
@@ -869,10 +905,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
if (!is_forward_declaration) {
- // Always start the definition for a class type so that
- // if the class has child classes or types that require
- // the class to be created for use as their decl contexts
- // the class will be ready to accept these child definitions.
+ // Always start the definition for a class type so that if the class
+ // has child classes or types that require the class to be created
+ // for use as their decl contexts the class will be ready to accept
+ // these child definitions.
if (die.HasChildren() == false) {
// No children for this struct/union/class, lets finish it
if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
@@ -896,33 +932,30 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
}
} else if (clang_type_was_created) {
- // Start the definition if the class is not objective C since
- // the underlying decls respond to isCompleteDefinition(). Objective
+ // Start the definition if the class is not objective C since the
+ // underlying decls respond to isCompleteDefinition(). Objective
// C decls don't respond to isCompleteDefinition() so we can't
// start the declaration definition right away. For C++
- // class/union/structs
- // we want to start the definition in case the class is needed as
- // the
- // declaration context for a contained class or type without the
- // need
- // to complete that type..
+ // class/union/structs we want to start the definition in case the
+ // class is needed as the declaration context for a contained class
+ // or type without the need to complete that type..
if (class_language != eLanguageTypeObjC &&
class_language != eLanguageTypeObjC_plus_plus)
ClangASTContext::StartTagDeclarationDefinition(clang_type);
- // Leave this as a forward declaration until we need
- // to know the details of the type. lldb_private::Type
- // will automatically call the SymbolFile virtual function
- // "SymbolFileDWARF::CompleteType(Type *)"
- // When the definition needs to be defined.
+ // Leave this as a forward declaration until we need to know the
+ // details of the type. lldb_private::Type will automatically call
+ // the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)" When the definition
+ // needs to be defined.
assert(!dwarf->GetForwardDeclClangTypeToDie().count(
ClangUtil::RemoveFastQualifiers(clang_type)
.GetOpaqueQualType()) &&
"Type already in the forward declaration map!");
- // Can't assume m_ast.GetSymbolFile() is actually a SymbolFileDWARF,
- // it can be a
- // SymbolFileDWARFDebugMap for Apple binaries.
+ // Can't assume m_ast.GetSymbolFile() is actually a
+ // SymbolFileDWARF, it can be a SymbolFileDWARFDebugMap for Apple
+ // binaries.
dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] =
clang_type.GetOpaqueQualType();
dwarf->GetForwardDeclClangTypeToDie()
@@ -931,6 +964,19 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
}
}
+
+ // If we made a clang type, set the trivial abi if applicable: We only
+ // do this for pass by value - which implies the Trivial ABI. There
+ // isn't a way to assert that something that would normally be pass by
+ // value is pass by reference, so we ignore that attribute if set.
+ if (calling_convention == llvm::dwarf::DW_CC_pass_by_value) {
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+ if (record_decl) {
+ record_decl->setHasTrivialSpecialMemberForCall();
+ }
+ }
+
} break;
case DW_TAG_enumeration_type: {
@@ -1008,9 +1054,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
SymbolFileDWARFDebugMap *debug_map_symfile =
dwarf->GetDebugMapSymfile();
if (debug_map_symfile) {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
type_sp =
debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
die_decl_ctx);
@@ -1027,9 +1072,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_sp->GetID());
}
- // We found a real definition for this type elsewhere
- // so lets use it and cache the fact that we found
- // a complete type for this die
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this
+ // die
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
clang::DeclContext *defn_decl_ctx =
GetCachedClangDeclContextForDIE(dwarf->DebugInfo()->GetDIE(
@@ -1145,9 +1190,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
- break; // mangled =
- // form_value.AsCString(&dwarf->get_debug_str_data());
- // break;
+ mangled_name_cstr = form_value.AsCString();
+ break;
case DW_AT_type:
type_die_form = form_value;
break;
@@ -1256,8 +1300,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
// Start off static. This will be set to false in
- // ParseChildParameters(...)
- // if we find a "this" parameters as the first parameter
+ // ParseChildParameters(...) if we find a "this" parameters as the
+ // first parameter
if (is_cxx_method) {
is_static = true;
}
@@ -1272,25 +1316,22 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
bool ignore_containing_context = false;
// Check for templatized class member functions. If we had any
- // DW_TAG_template_type_parameter
- // or DW_TAG_template_value_parameter the DW_TAG_subprogram DIE, then we
- // can't let this become
- // a method in a class. Why? Because templatized functions are only
- // emitted if one of the
- // templatized methods is used in the current compile unit and we will
- // end up with classes
- // that may or may not include these member functions and this means one
- // class won't match another
- // class definition and it affects our ability to use a class in the
- // clang expression parser. So
- // for the greater good, we currently must not allow any template member
- // functions in a class definition.
+ // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
+ // the DW_TAG_subprogram DIE, then we can't let this become a method in
+ // a class. Why? Because templatized functions are only emitted if one
+ // of the templatized methods is used in the current compile unit and
+ // we will end up with classes that may or may not include these member
+ // functions and this means one class won't match another class
+ // definition and it affects our ability to use a class in the clang
+ // expression parser. So for the greater good, we currently must not
+ // allow any template member functions in a class definition.
if (is_cxx_method && has_template_params) {
ignore_containing_context = true;
is_cxx_method = false;
}
- // clang_type will get the function prototype clang type after this call
+ // clang_type will get the function prototype clang type after this
+ // call
clang_type = m_ast.CreateFunctionType(
return_clang_type, function_param_types.data(),
function_param_types.size(), is_variadic, type_quals);
@@ -1318,8 +1359,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (class_opaque_type) {
// If accessibility isn't set to anything valid, assume public
- // for
- // now...
+ // for now...
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
@@ -1341,9 +1381,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
}
} else if (is_cxx_method) {
- // Look at the parent of this DIE and see if is is
- // a class or struct and see if this is actually a
- // C++ method
+ // Look at the parent of this DIE and see if is is a class or
+ // struct and see if this is actually a C++ method
Type *class_type = dwarf->ResolveType(decl_ctx_die);
if (class_type) {
bool alternate_defn = false;
@@ -1352,10 +1391,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
alternate_defn = true;
// We uniqued the parent class of this function to another
- // class
- // so we now need to associate all dies under "decl_ctx_die"
- // to
- // DIEs in the DIE for "class_type"...
+ // class so we now need to associate all dies under
+ // "decl_ctx_die" to DIEs in the DIE for "class_type"...
SymbolFileDWARF *class_symfile = NULL;
DWARFDIE class_type_die;
@@ -1381,10 +1418,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
// FIXME do something with these failures that's smarter
// than
// just dropping them on the ground. Unfortunately classes
- // don't
- // like having stuff added to them after their definitions
- // are
- // complete...
+ // don't like having stuff added to them after their
+ // definitions are complete...
type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
@@ -1396,16 +1431,13 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (specification_die_form.IsValid()) {
// We have a specification which we are going to base our
- // function
- // prototype off of, so we need this type to be completed so
- // that the
- // m_die_to_decl_ctx for the method in the specification has a
- // valid
- // clang decl context.
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the specification has a valid clang decl context.
class_type->GetForwardCompilerType();
// If we have a specification, then the function type should
- // have been
- // made with the specification and not with this die.
+ // have been made with the specification and not with this
+ // die.
DWARFDIE spec_die = dwarf->DebugInfo()->GetDIE(
DIERef(specification_die_form));
clang::DeclContext *spec_clang_decl_ctx =
@@ -1421,12 +1453,9 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
type_handled = true;
} else if (abstract_origin_die_form.IsValid()) {
// We have a specification which we are going to base our
- // function
- // prototype off of, so we need this type to be completed so
- // that the
- // m_die_to_decl_ctx for the method in the abstract origin has
- // a valid
- // clang decl context.
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the abstract origin has a valid clang decl context.
class_type->GetForwardCompilerType();
DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE(
@@ -1449,17 +1478,16 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (class_opaque_type.IsBeingDefined() || alternate_defn) {
if (!is_static && !die.HasChildren()) {
// We have a C++ member function with no children (this
- // pointer!)
- // and clang will get mad if we try and make a function
- // that isn't
- // well formed in the DWARF, so we will just skip it...
+ // pointer!) and clang will get mad if we try and make
+ // a function that isn't well formed in the DWARF, so
+ // we will just skip it...
type_handled = true;
} else {
bool add_method = true;
if (alternate_defn) {
// If an alternate definition for the class exists,
- // then add the method only if an
- // equivalent is not already present.
+ // then add the method only if an equivalent is not
+ // already present.
clang::CXXRecordDecl *record_decl =
m_ast.GetAsCXXRecordDecl(
class_opaque_type.GetOpaqueQualType());
@@ -1499,18 +1527,18 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
const bool is_attr_used = false;
// Neither GCC 4.2 nor clang++ currently set a valid
- // accessibility
- // in the DWARF for C++ methods... Default to public
- // for now...
+ // accessibility in the DWARF for C++ methods...
+ // Default to public for now...
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
clang::CXXMethodDecl *cxx_method_decl =
m_ast.AddMethodToCXXRecordType(
class_opaque_type.GetOpaqueQualType(),
- type_name_cstr, clang_type, accessibility,
- is_virtual, is_static, is_inline, is_explicit,
- is_attr_used, is_artificial);
+ type_name_cstr, mangled_name_cstr, clang_type,
+ accessibility, is_virtual, is_static,
+ is_inline, is_explicit, is_attr_used,
+ is_artificial);
type_handled = cxx_method_decl != NULL;
@@ -1541,25 +1569,21 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
} else {
// We were asked to parse the type for a method in a
- // class, yet the
- // class hasn't been asked to complete itself through the
- // clang::ExternalASTSource protocol, so we need to just
- // have the
- // class complete itself and do things the right way, then
- // our
+ // class, yet the class hasn't been asked to complete
+ // itself through the clang::ExternalASTSource protocol,
+ // so we need to just have the class complete itself and
+ // do things the right way, then our
// DIE should then have an entry in the
// dwarf->GetDIEToType() map. First
// we need to modify the dwarf->GetDIEToType() so it
- // doesn't think we are
- // trying to parse this DIE anymore...
+ // doesn't think we are trying to parse this DIE
+ // anymore...
dwarf->GetDIEToType()[die.GetDIE()] = NULL;
// Now we get the full type to force our class type to
- // complete itself
- // using the clang::ExternalASTSource protocol which will
- // parse all
- // base classes and all methods (including the method for
- // this DIE).
+ // complete itself using the clang::ExternalASTSource
+ // protocol which will parse all base classes and all
+ // methods (including the method for this DIE).
class_type->GetFullCompilerType();
// The type for this DIE should have been filled in the
@@ -1573,8 +1597,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
// FIXME This is fixing some even uglier behavior but we
// really need to
// uniq the methods of each class as well as the class
- // itself.
- // <rdar://problem/11240464>
+ // itself. <rdar://problem/11240464>
type_handled = true;
}
}
@@ -1737,8 +1760,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
array_element_type.GetCompleteType() == false) {
ModuleSP module_sp = die.GetModule();
if (module_sp) {
- if (die.GetCU()->GetProducer() ==
- DWARFCompileUnit::eProducerClang)
+ if (die.GetCU()->GetProducer() == eProducerClang)
module_sp->ReportError(
"DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
"class/union/struct element type DIE 0x%8.8x that is a "
@@ -1760,11 +1782,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
// We have no choice other than to pretend that the element class
- // type
- // is complete. If we don't do this, clang will crash when trying
- // to layout the class. Since we provide layout assistance, all
- // ivars in this class and other classes will be fine, this is
- // the best we can do short of crashing.
+ // type is complete. If we don't do this, clang will crash when
+ // trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will be
+ // fine, this is the best we can do short of crashing.
if (ClangASTContext::StartTagDeclarationDefinition(
array_element_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(
@@ -1864,7 +1885,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = NULL;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != NULL && sc_parent_die) {
symbol_context_scope =
@@ -1956,6 +1978,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
const DWARFDIE &die,
ClangASTContext::TemplateParameterInfos &template_param_infos) {
const dw_tag_t tag = die.Tag();
+ bool is_template_template_argument = false;
switch (tag) {
case DW_TAG_GNU_template_parameter_pack: {
@@ -1971,11 +1994,15 @@ bool DWARFASTParserClang::ParseTemplateDIE(
}
return true;
}
+ case DW_TAG_GNU_template_template_param:
+ is_template_template_argument = true;
+ LLVM_FALLTHROUGH;
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter: {
DWARFAttributes attributes;
const size_t num_attributes = die.GetAttributes(attributes);
const char *name = nullptr;
+ const char *template_name = nullptr;
CompilerType clang_type;
uint64_t uval64 = 0;
bool uval64_valid = false;
@@ -1990,6 +2017,11 @@ bool DWARFASTParserClang::ParseTemplateDIE(
name = form_value.AsCString();
break;
+ case DW_AT_GNU_template_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ template_name = form_value.AsCString();
+ break;
+
case DW_AT_type:
if (attributes.ExtractFormValueAtIndex(i, form_value)) {
Type *lldb_type = die.ResolveTypeUID(DIERef(form_value));
@@ -2013,7 +2045,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
if (!clang_type)
clang_type = m_ast.GetBasicType(eBasicTypeVoid);
- if (clang_type) {
+ if (!is_template_template_argument) {
bool is_signed = false;
if (name && name[0])
template_param_infos.names.push_back(name);
@@ -2033,7 +2065,10 @@ bool DWARFASTParserClang::ParseTemplateDIE(
clang::TemplateArgument(ClangUtil::GetQualType(clang_type)));
}
} else {
- return false;
+ auto *tplt_type = m_ast.CreateTemplateTemplateParmDecl(template_name);
+ template_param_infos.names.push_back(name);
+ template_param_infos.args.push_back(
+ clang::TemplateArgument(clang::TemplateName(tplt_type)));
}
}
}
@@ -2052,7 +2087,6 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
if (!parent_die)
return false;
- Args template_parameter_names;
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
die = die.GetSibling()) {
const dw_tag_t tag = die.Tag();
@@ -2061,6 +2095,7 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
case DW_TAG_GNU_template_parameter_pack:
+ case DW_TAG_GNU_template_template_param:
ParseTemplateDIE(die, template_param_infos);
break;
@@ -2073,6 +2108,95 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
return template_param_infos.args.size() == template_param_infos.names.size();
}
+// Checks whether m1 is an overload of m2 (as opposed to an override). This is
+// called by addOverridesForMethod to distinguish overrides (which share a
+// vtable entry) from overloads (which require distinct entries).
+static bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) {
+ // FIXME: This should detect covariant return types, but currently doesn't.
+ lldbassert(&m1->getASTContext() == &m2->getASTContext() &&
+ "Methods should have the same AST context");
+ clang::ASTContext &context = m1->getASTContext();
+
+ const auto *m1Type =
+ llvm::cast<clang::FunctionProtoType>(
+ context.getCanonicalType(m1->getType()));
+
+ const auto *m2Type =
+ llvm::cast<clang::FunctionProtoType>(
+ context.getCanonicalType(m2->getType()));
+
+ auto compareArgTypes =
+ [&context](const clang::QualType &m1p, const clang::QualType &m2p) {
+ return context.hasSameType(m1p.getUnqualifiedType(),
+ m2p.getUnqualifiedType());
+ };
+
+ // FIXME: In C++14 and later, we can just pass m2Type->param_type_end()
+ // as a fourth parameter to std::equal().
+ return (m1->getNumParams() != m2->getNumParams()) ||
+ !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(),
+ m2Type->param_type_begin(), compareArgTypes);
+}
+
+// If decl is a virtual method, walk the base classes looking for methods that
+// decl overrides. This table of overridden methods is used by IRGen to
+// determine the vtable layout for decl's parent class.
+static void addOverridesForMethod(clang::CXXMethodDecl *decl) {
+ if (!decl->isVirtual())
+ return;
+
+ clang::CXXBasePaths paths;
+
+ auto find_overridden_methods =
+ [decl](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) {
+ if (auto *base_record =
+ llvm::dyn_cast<clang::CXXRecordDecl>(
+ specifier->getType()->getAs<clang::RecordType>()->getDecl())) {
+
+ clang::DeclarationName name = decl->getDeclName();
+
+ // If this is a destructor, check whether the base class destructor is
+ // virtual.
+ if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
+ if (auto *baseDtorDecl = base_record->getDestructor()) {
+ if (baseDtorDecl->isVirtual()) {
+ path.Decls = baseDtorDecl;
+ return true;
+ } else
+ return false;
+ }
+
+ // Otherwise, search for name in the base class.
+ for (path.Decls = base_record->lookup(name); !path.Decls.empty();
+ path.Decls = path.Decls.slice(1)) {
+ if (auto *method_decl =
+ llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
+ if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
+ path.Decls = method_decl;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) {
+ for (auto *overridden_decl : paths.found_decls())
+ decl->addOverriddenMethod(
+ llvm::cast<clang::CXXMethodDecl>(overridden_decl));
+ }
+}
+
+// If clang_type is a CXXRecordDecl, builds the method override list for each
+// of its virtual methods.
+static void addMethodOverrides(ClangASTContext &ast, CompilerType &clang_type) {
+ if (auto *record =
+ ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()))
+ for (auto *method : record->methods())
+ addOverridesForMethod(method);
+}
+
bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
lldb_private::Type *type,
CompilerType &clang_type) {
@@ -2090,10 +2214,10 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
#if defined LLDB_CONFIGURATION_DEBUG
//----------------------------------------------------------------------
- // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES
- // environment variable can be set with one or more typenames separated
- // by ';' characters. This will cause this function to not complete any
- // types whose names match.
+ // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES environment
+ // variable can be set with one or more typenames separated by ';'
+ // characters. This will cause this function to not complete any types whose
+ // names match.
//
// Examples of setting this environment variable:
//
@@ -2144,8 +2268,8 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
LanguageType class_language = eLanguageTypeUnknown;
if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) {
class_language = eLanguageTypeObjC;
- // For objective C we don't start the definition when
- // the class is created.
+ // For objective C we don't start the definition when the class is
+ // created.
ClangASTContext::StartTagDeclarationDefinition(clang_type);
}
@@ -2217,29 +2341,27 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
clang::TTK_Class);
}
- // Since DW_TAG_structure_type gets used for both classes
- // and structures, we may need to set any DW_TAG_member
- // fields to have a "private" access if none was specified.
- // When we parsed the child members we tracked that actual
- // accessibility value for each DW_TAG_member in the
- // "member_accessibilities" array. If the value for the
- // member is zero, then it was set to the "default_accessibility"
- // which for structs was "public". Below we correct this
- // by setting any fields to "private" that weren't correctly
- // set.
+ // Since DW_TAG_structure_type gets used for both classes and
+ // structures, we may need to set any DW_TAG_member fields to have a
+ // "private" access if none was specified. When we parsed the child
+ // members we tracked that actual accessibility value for each
+ // DW_TAG_member in the "member_accessibilities" array. If the value
+ // for the member is zero, then it was set to the
+ // "default_accessibility" which for structs was "public". Below we
+ // correct this by setting any fields to "private" that weren't
+ // correctly set.
if (is_a_class && !member_accessibilities.empty()) {
- // This is a class and all members that didn't have
- // their access specified are private.
+ // This is a class and all members that didn't have their access
+ // specified are private.
m_ast.SetDefaultAccessForRecordFields(
m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
&member_accessibilities.front(), member_accessibilities.size());
}
if (!base_classes.empty()) {
- // Make sure all base classes refer to complete types and not
- // forward declarations. If we don't do this, clang will crash
- // with an assertion in the call to
- // clang_type.SetBaseClassesForClassType()
+ // Make sure all base classes refer to complete types and not forward
+ // declarations. If we don't do this, clang will crash with an
+ // assertion in the call to clang_type.SetBaseClassesForClassType()
for (auto &base_class : base_classes) {
clang::TypeSourceInfo *type_source_info =
base_class->getTypeSourceInfo();
@@ -2252,19 +2374,17 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
"does not have a complete definition.",
die.GetName(),
base_class_type.GetTypeName().GetCString());
- if (die.GetCU()->GetProducer() ==
- DWARFCompileUnit::eProducerClang)
+ if (die.GetCU()->GetProducer() == eProducerClang)
module->ReportError(":: Try compiling the source file with "
"-fstandalone-debug.");
// We have no choice other than to pretend that the base class
// is complete. If we don't do this, clang will crash when we
// call setBases() inside of
- // "clang_type.SetBaseClassesForClassType()"
- // below. Since we provide layout assistance, all ivars in this
- // class and other classes will be fine, this is the best we can
- // do
- // short of crashing.
+ // "clang_type.SetBaseClassesForClassType()" below. Since we
+ // provide layout assistance, all ivars in this class and other
+ // classes will be fine, this is the best we can do short of
+ // crashing.
if (ClangASTContext::StartTagDeclarationDefinition(
base_class_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(
@@ -2277,14 +2397,15 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
&base_classes.front(),
base_classes.size());
- // Clang will copy each CXXBaseSpecifier in "base_classes"
- // so we have to free them all.
+ // Clang will copy each CXXBaseSpecifier in "base_classes" so we have
+ // to free them all.
ClangASTContext::DeleteBaseClassSpecifiers(&base_classes.front(),
base_classes.size());
}
}
}
+ addMethodOverrides(m_ast, clang_type);
ClangASTContext::BuildIndirectFields(clang_type);
ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
@@ -2582,14 +2703,13 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
Mangled func_name;
if (mangled)
func_name.SetValue(ConstString(mangled), true);
- else if (die.GetParent().Tag() == DW_TAG_compile_unit &&
+ else if ((die.GetParent().Tag() == DW_TAG_compile_unit ||
+ die.GetParent().Tag() == DW_TAG_partial_unit) &&
Language::LanguageIsCPlusPlus(die.GetLanguage()) && name &&
strcmp(name, "main") != 0) {
// If the mangled name is not present in the DWARF, generate the
- // demangled name
- // using the decl context. We skip if the function is "main" as its name
- // is
- // never mangled.
+ // demangled name using the decl context. We skip if the function is
+ // "main" as its name is never mangled.
bool is_static = false;
bool is_variadic = false;
bool has_template_params = false;
@@ -2748,8 +2868,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (form_value.BlockData()) {
Value initialValue(0);
Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data =
- die.GetDWARF()->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = die.GetData();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset =
form_value.BlockData() - debug_info_data.GetDataStart();
@@ -2763,8 +2882,8 @@ bool DWARFASTParserClang::ParseChildMembers(
}
} else {
// With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
member_byte_offset = form_value.Unsigned();
}
break;
@@ -2806,8 +2925,8 @@ bool DWARFASTParserClang::ParseChildMembers(
ConstString fixed_getter;
ConstString fixed_setter;
- // Check if the property getter/setter were provided as full
- // names. We want basenames, so we extract them.
+ // Check if the property getter/setter were provided as full names.
+ // We want basenames, so we extract them.
if (prop_getter_name && prop_getter_name[0] == '-') {
ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
@@ -2819,8 +2938,7 @@ bool DWARFASTParserClang::ParseChildMembers(
prop_setter_name = prop_setter_method.GetSelector().GetCString();
}
- // If the names haven't been provided, they need to be
- // filled in.
+ // If the names haven't been provided, they need to be filled in.
if (!prop_getter_name) {
prop_getter_name = prop_name;
@@ -2836,19 +2954,18 @@ bool DWARFASTParserClang::ParseChildMembers(
}
}
- // Clang has a DWARF generation bug where sometimes it
- // represents fields that are references with bad byte size
- // and bit size/offset information such as:
+ // Clang has a DWARF generation bug where sometimes it represents
+ // fields that are references with bad byte size and bit size/offset
+ // information such as:
//
// DW_AT_byte_size( 0x00 )
// DW_AT_bit_size( 0x40 )
// DW_AT_bit_offset( 0xffffffffffffffc0 )
//
- // So check the bit offset to make sure it is sane, and if
- // the values are not sane, remove them. If we don't do this
- // then we will end up with a crash if we try to use this
- // type in an expression when clang becomes unhappy with its
- // recycled debug info.
+ // So check the bit offset to make sure it is sane, and if the values
+ // are not sane, remove them. If we don't do this then we will end up
+ // with a crash if we try to use this type in an expression when clang
+ // becomes unhappy with its recycled debug info.
if (byte_size == 0 && bit_offset < 0) {
bit_size = 0;
@@ -2862,12 +2979,10 @@ bool DWARFASTParserClang::ParseChildMembers(
if (member_idx == 0 && !is_artificial && name &&
(strstr(name, "_vptr$") == name)) {
- // Not all compilers will mark the vtable pointer
- // member as artificial (llvm-gcc). We can't have
- // the virtual members in our classes otherwise it
- // throws off all child offsets since we end up
- // having and extra pointer sized member in our
- // class layouts.
+ // Not all compilers will mark the vtable pointer member as
+ // artificial (llvm-gcc). We can't have the virtual members in our
+ // classes otherwise it throws off all child offsets since we end up
+ // having and extra pointer sized member in our class layouts.
is_artificial = true;
}
@@ -2907,15 +3022,15 @@ bool DWARFASTParserClang::ParseChildMembers(
/////////////////////////////////////////////////////////////
// How to locate a field given the DWARF debug information
//
- // AT_byte_size indicates the size of the word in which the
- // bit offset must be interpreted.
+ // AT_byte_size indicates the size of the word in which the bit
+ // offset must be interpreted.
//
// AT_data_member_location indicates the byte offset of the
// word from the base address of the structure.
//
// AT_bit_offset indicates how many bits into the word
- // (according to the host endianness) the low-order bit of
- // the field starts. AT_bit_offset can be negative.
+ // (according to the host endianness) the low-order bit of the
+ // field starts. AT_bit_offset can be negative.
//
// AT_bit_size indicates the size of the field in bits.
/////////////////////////////////////////////////////////////
@@ -2956,12 +3071,9 @@ bool DWARFASTParserClang::ParseChildMembers(
field_bit_offset = this_field_info.bit_offset;
// If the member to be emitted did not start on a character
- // boundary and there is
- // empty space between the last field and this one, then we need
- // to emit an
- // anonymous member filling up the space up to its start. There
- // are three cases
- // here:
+ // boundary and there is empty space between the last field and
+ // this one, then we need to emit an anonymous member filling
+ // up the space up to its start. There are three cases here:
//
// 1 If the previous member ended on a character boundary, then
// we can emit an
@@ -2986,10 +3098,8 @@ bool DWARFASTParserClang::ParseChildMembers(
const uint64_t word_width = 32;
// Objective-C has invalid DW_AT_bit_offset values in older
- // versions
- // of clang, so we have to be careful and only insert unnamed
- // bitfields
- // if we have a new enough clang.
+ // versions of clang, so we have to be careful and only insert
+ // unnamed bitfields if we have a new enough clang.
bool detect_unnamed_bitfields = true;
if (class_language == eLanguageTypeObjC ||
@@ -3052,10 +3162,10 @@ bool DWARFASTParserClang::ParseChildMembers(
{
// Older versions of clang emit array[0] and array[1] in the
- // same way (<rdar://problem/12566646>).
- // If the current field is at the end of the structure, then
- // there is definitely no room for extra
- // elements and we override the type to array[0].
+ // same way (<rdar://problem/12566646>). If the current field
+ // is at the end of the structure, then there is definitely no
+ // room for extra elements and we override the type to
+ // array[0].
CompilerType member_array_element_type;
uint64_t member_array_size;
@@ -3089,8 +3199,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (ClangASTContext::IsCXXClassType(member_clang_type) &&
member_clang_type.GetCompleteType() == false) {
- if (die.GetCU()->GetProducer() ==
- DWARFCompileUnit::eProducerClang)
+ if (die.GetCU()->GetProducer() == eProducerClang)
module_sp->ReportError(
"DWARF DIE at 0x%8.8x (class %s) has a member variable "
"0x%8.8x (%s) whose type is a forward declaration, not a "
@@ -3108,12 +3217,11 @@ bool DWARFASTParserClang::ParseChildMembers(
die.GetOffset(), name,
sc.comp_unit ? sc.comp_unit->GetPath().c_str()
: "the source file");
- // We have no choice other than to pretend that the member class
- // is complete. If we don't do this, clang will crash when
- // trying
- // to layout the class. Since we provide layout assistance, all
- // ivars in this class and other classes will be fine, this is
- // the best we can do short of crashing.
+ // We have no choice other than to pretend that the member
+ // class is complete. If we don't do this, clang will crash
+ // when trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will
+ // be fine, this is the best we can do short of crashing.
if (ClangASTContext::StartTagDeclarationDefinition(
member_clang_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(
@@ -3221,8 +3329,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (form_value.BlockData()) {
Value initialValue(0);
Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data =
- die.GetDWARF()->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = die.GetData();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset =
form_value.BlockData() - debug_info_data.GetDataStart();
@@ -3235,8 +3342,8 @@ bool DWARFASTParserClang::ParseChildMembers(
}
} else {
// With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
member_byte_offset = form_value.Unsigned();
}
break;
@@ -3282,18 +3389,16 @@ bool DWARFASTParserClang::ParseChildMembers(
if (is_virtual) {
// Do not specify any offset for virtual inheritance. The DWARF
- // produced by clang doesn't
- // give us a constant offset, but gives us a DWARF expressions that
- // requires an actual object
- // in memory. the DW_AT_data_member_location for a virtual base
- // class looks like:
+ // produced by clang doesn't give us a constant offset, but gives
+ // us a DWARF expressions that requires an actual object in memory.
+ // the DW_AT_data_member_location for a virtual base class looks
+ // like:
// DW_AT_data_member_location( DW_OP_dup, DW_OP_deref,
// DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref,
// DW_OP_plus )
// Given this, there is really no valid response we can give to
- // clang for virtual base
- // class offsets, and this should eventually be removed from
- // LayoutRecordType() in the external
+ // clang for virtual base class offsets, and this should eventually
+ // be removed from LayoutRecordType() in the external
// AST source in clang.
} else {
layout_info.base_offsets.insert(std::make_pair(
@@ -3365,22 +3470,6 @@ size_t DWARFASTParserClang::ParseChildParameters(
is_artificial = form_value.Boolean();
break;
case DW_AT_location:
- // if (form_value.BlockData())
- // {
- // const DWARFDataExtractor&
- // debug_info_data = debug_info();
- // uint32_t block_length =
- // form_value.Unsigned();
- // DWARFDataExtractor
- // location(debug_info_data,
- // form_value.BlockData() -
- // debug_info_data.GetDataStart(),
- // block_length);
- // }
- // else
- // {
- // }
- // break;
case DW_AT_const_value:
case DW_AT_default_value:
case DW_AT_description:
@@ -3397,52 +3486,29 @@ size_t DWARFASTParserClang::ParseChildParameters(
}
bool skip = false;
- if (skip_artificial) {
- if (is_artificial) {
- // In order to determine if a C++ member function is
- // "const" we have to look at the const-ness of "this"...
- // Ugly, but that
- if (arg_idx == 0) {
- if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind())) {
- // Often times compilers omit the "this" name for the
- // specification DIEs, so we can't rely upon the name
- // being in the formal parameter DIE...
- if (name == NULL || ::strcmp(name, "this") == 0) {
- Type *this_type =
- die.ResolveTypeUID(DIERef(param_type_die_form));
- if (this_type) {
- uint32_t encoding_mask = this_type->GetEncodingMask();
- if (encoding_mask & Type::eEncodingIsPointerUID) {
- is_static = false;
-
- if (encoding_mask & (1u << Type::eEncodingIsConstUID))
- type_quals |= clang::Qualifiers::Const;
- if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
- type_quals |= clang::Qualifiers::Volatile;
- }
- }
- }
- }
- }
- skip = true;
- } else {
-
- // HACK: Objective C formal parameters "self" and "_cmd"
- // are not marked as artificial in the DWARF...
- CompileUnit *comp_unit = die.GetLLDBCompileUnit();
- if (comp_unit) {
- switch (comp_unit->GetLanguage()) {
- case eLanguageTypeObjC:
- case eLanguageTypeObjC_plus_plus:
- if (name && name[0] &&
- (strcmp(name, "self") == 0 || strcmp(name, "_cmd") == 0))
- skip = true;
- break;
- default:
- break;
+ if (skip_artificial && is_artificial) {
+ // In order to determine if a C++ member function is "const" we
+ // have to look at the const-ness of "this"...
+ if (arg_idx == 0 &&
+ DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()) &&
+ // Often times compilers omit the "this" name for the
+ // specification DIEs, so we can't rely upon the name being in
+ // the formal parameter DIE...
+ (name == NULL || ::strcmp(name, "this") == 0)) {
+ Type *this_type = die.ResolveTypeUID(DIERef(param_type_die_form));
+ if (this_type) {
+ uint32_t encoding_mask = this_type->GetEncodingMask();
+ if (encoding_mask & Type::eEncodingIsPointerUID) {
+ is_static = false;
+
+ if (encoding_mask & (1u << Type::eEncodingIsConstUID))
+ type_quals |= clang::Qualifiers::Const;
+ if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
+ type_quals |= clang::Qualifiers::Volatile;
}
}
}
+ skip = true;
}
if (!skip) {
@@ -3470,10 +3536,10 @@ size_t DWARFASTParserClang::ParseChildParameters(
case DW_TAG_template_type_parameter:
case DW_TAG_template_value_parameter:
case DW_TAG_GNU_template_parameter_pack:
- // The one caller of this was never using the template_param_infos,
- // and the local variable was taking up a large amount of stack space
- // in SymbolFileDWARF::ParseType() so this was removed. If we ever need
- // the template params back, we can add them back.
+ // The one caller of this was never using the template_param_infos, and
+ // the local variable was taking up a large amount of stack space in
+ // SymbolFileDWARF::ParseType() so this was removed. If we ever need the
+ // template params back, we can add them back.
// ParseTemplateDIE (dwarf_cu, die, template_param_infos);
has_template_params = true;
break;
@@ -3692,6 +3758,7 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
bool try_parsing_type = true;
switch (die.Tag()) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
decl_ctx = m_ast.GetTranslationUnitDecl();
try_parsing_type = false;
break;
@@ -4008,8 +4075,8 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
// Now do the work of linking the DeclContexts and Types.
if (fast_path) {
- // We can do this quickly. Just run across the tables index-for-index since
- // we know each node has matching names and tags.
+ // We can do this quickly. Just run across the tables index-for-index
+ // since we know each node has matching names and tags.
for (idx = 0; idx < src_size; ++idx) {
src_die = src_name_to_die.GetValueAtIndexUnchecked(idx);
dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
@@ -4046,9 +4113,9 @@ bool DWARFASTParserClang::CopyUniqueClassMethodTypes(
}
}
} else {
- // We must do this slowly. For each member of the destination, look
- // up a member in the source with the same name, check its tag, and
- // unique them if everything matches up. Report failures.
+ // We must do this slowly. For each member of the destination, look up a
+ // member in the source with the same name, check its tag, and unique them
+ // if everything matches up. Report failures.
if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty()) {
src_name_to_die.Sort();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
index e04dc76d1dbe..328212e4b684 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
@@ -10,7 +10,6 @@
#include "DWARFASTParserGo.h"
#include "DWARFASTParserGo.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugInfo.h"
@@ -158,7 +157,8 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
Type *type = dwarf->ResolveTypeUID(encoding_uid);
if (type) {
if (go_kind == 0 && type->GetName() == type_name_const_str) {
- // Go emits extra typedefs as a forward declaration. Ignore these.
+ // Go emits extra typedefs as a forward declaration. Ignore
+ // these.
dwarf->m_die_to_type[die.GetDIE()] = type;
return type->shared_from_this();
}
@@ -213,10 +213,10 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
// TODO(ribrdb): Do we need this?
- // UniqueDWARFASTType is large, so don't create a local variables on the
- // stack, put it on the heap. This function is often called recursively
- // and clang isn't good and sharing the stack space for variables in
- // different blocks.
+ // UniqueDWARFASTType is large, so don't create a local variables on
+ // the stack, put it on the heap. This function is often called
+ // recursively and clang isn't good and sharing the stack space for
+ // variables in different blocks.
std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(
new UniqueDWARFASTType());
@@ -225,11 +225,10 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
dwarf->GetUniqueDWARFASTTypeMap().Find(
type_name_const_str, die, decl,
byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) {
- // We have already parsed this type or from another
- // compile unit. GCC loves to use the "one definition
- // rule" which can result in multiple definitions
- // of the same class over and over in each compile
- // unit.
+ // We have already parsed this type or from another compile unit. GCC
+ // loves to use the "one definition rule" which can result in
+ // multiple definitions of the same class over and over in each
+ // compile unit.
type_sp = unique_ast_entry_ap->m_type_sp;
if (type_sp) {
dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
@@ -255,9 +254,9 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
Type::eEncodingIsUID, &decl, compiler_type,
Type::eResolveStateForward));
- // Add our type to the unique type map so we don't
- // end up creating many copies of the same type over
- // and over in the ASTContext for our module
+ // Add our type to the unique type map so we don't end up creating many
+ // copies of the same type over and over in the ASTContext for our
+ // module
unique_ast_entry_ap->m_type_sp = type_sp;
unique_ast_entry_ap->m_die = die;
unique_ast_entry_ap->m_declaration = decl;
@@ -266,19 +265,19 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
*unique_ast_entry_ap);
if (!is_forward_declaration) {
- // Always start the definition for a class type so that
- // if the class has child classes or types that require
- // the class to be created for use as their decl contexts
- // the class will be ready to accept these child definitions.
+ // Always start the definition for a class type so that if the class
+ // has child classes or types that require the class to be created
+ // for use as their decl contexts the class will be ready to accept
+ // these child definitions.
if (die.HasChildren() == false) {
// No children for this struct/union/class, lets finish it
m_ast.CompleteStructType(compiler_type);
} else if (compiler_type_was_created) {
- // Leave this as a forward declaration until we need
- // to know the details of the type. lldb_private::Type
- // will automatically call the SymbolFile virtual function
- // "SymbolFileDWARF::CompleteType(Type *)"
- // When the definition needs to be defined.
+ // Leave this as a forward declaration until we need to know the
+ // details of the type. lldb_private::Type will automatically call
+ // the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)" When the definition
+ // needs to be defined.
dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] =
compiler_type.GetOpaqueQualType();
dwarf->m_forward_decl_clang_type_to_die[compiler_type
@@ -432,7 +431,8 @@ TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = NULL;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != NULL && sc_parent_die) {
symbol_context_scope =
@@ -655,8 +655,7 @@ size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc,
if (form_value.BlockData()) {
Value initialValue(0);
Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data =
- die.GetDWARF()->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = die.GetData();
uint32_t block_length = form_value.Unsigned();
uint32_t block_offset =
form_value.BlockData() - debug_info_data.GetDataStart();
@@ -670,8 +669,8 @@ size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc,
}
} else {
// With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning
- // of the containing entity.
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
member_byte_offset = form_value.Unsigned();
}
break;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
index 8b5202ba265f..476394487985 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
@@ -9,7 +9,7 @@
#include "DWARFASTParserJava.h"
#include "DWARFAttribute.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDeclContext.h"
@@ -324,7 +324,8 @@ lldb::TypeSP DWARFASTParserJava::ParseTypeFromDWARF(
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = nullptr;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != nullptr && sc_parent_die) {
symbol_context_scope =
@@ -418,7 +419,7 @@ bool DWARFASTParserJava::CompleteTypeFromDWARF(
void DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die,
CompilerType &compiler_type) {
- DWARFCompileUnit *dwarf_cu = parent_die.GetCU();
+ DWARFUnit *dwarf_cu = parent_die.GetCU();
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
die = die.GetSibling()) {
switch (die.Tag()) {
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
index 3b1466df21b0..3ef5c2eb8626 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
@@ -98,7 +98,8 @@ lldb::TypeSP DWARFASTParserOCaml::ParseTypeFromDWARF(const SymbolContext &sc,
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
SymbolContextScope *symbol_context_scope = nullptr;
- if (sc_parent_tag == DW_TAG_compile_unit) {
+ if (sc_parent_tag == DW_TAG_compile_unit ||
+ sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
} else if (sc.function != nullptr && sc_parent_die) {
symbol_context_scope =
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
index e3b2279ca8fc..09cb5e14934f 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
@@ -4,7 +4,6 @@
#define SymbolFileDWARF_DWARFASTParserOCaml_h_
#include "DWARFASTParser.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDebugInfo.h"
#include "DWARFDefines.h"
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index bc49fc5de2cd..a765be0b46d0 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -10,6 +10,7 @@
#include "DWARFAbbreviationDeclaration.h"
#include "lldb/Core/dwarf.h"
+#include "lldb/Utility/Stream.h"
#include "DWARFFormValue.h"
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index 28e713f9beb1..b2296c455d6a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -13,8 +13,6 @@
#include "DWARFAttribute.h"
#include "SymbolFileDWARF.h"
-class DWARFCompileUnit;
-
class DWARFAbbreviationDeclaration {
public:
enum { InvalidCode = 0 };
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
index d2573f3742ba..2586d1f18530 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "DWARFAttribute.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
DWARFAttributes::DWARFAttributes() : m_infos() {}
@@ -26,7 +26,7 @@ uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const {
return UINT32_MAX;
}
-void DWARFAttributes::Append(const DWARFCompileUnit *cu,
+void DWARFAttributes::Append(const DWARFUnit *cu,
dw_offset_t attr_die_offset, dw_attr_t attr,
dw_form_t form) {
AttributeValue attr_value = {cu, attr_die_offset, {attr, form}};
@@ -48,12 +48,11 @@ bool DWARFAttributes::RemoveAttribute(dw_attr_t attr) {
bool DWARFAttributes::ExtractFormValueAtIndex(
uint32_t i, DWARFFormValue &form_value) const {
- const DWARFCompileUnit *cu = CompileUnitAtIndex(i);
+ const DWARFUnit *cu = CompileUnitAtIndex(i);
form_value.SetCompileUnit(cu);
form_value.SetForm(FormAtIndex(i));
lldb::offset_t offset = DIEOffsetAtIndex(i);
- return form_value.ExtractValue(
- cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset);
+ return form_value.ExtractValue(cu->GetData(), &offset);
}
uint64_t DWARFAttributes::FormValueAsUnsigned(dw_attr_t attr,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 317e710e6d94..db4324cf7725 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -14,7 +14,7 @@
#include "llvm/ADT/SmallVector.h"
#include <vector>
-class DWARFCompileUnit;
+class DWARFUnit;
class DWARFFormValue;
class DWARFAttribute {
@@ -50,9 +50,9 @@ public:
DWARFAttributes();
~DWARFAttributes();
- void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset,
+ void Append(const DWARFUnit *cu, dw_offset_t attr_die_offset,
dw_attr_t attr, dw_form_t form);
- const DWARFCompileUnit *CompileUnitAtIndex(uint32_t i) const {
+ const DWARFUnit *CompileUnitAtIndex(uint32_t i) const {
return m_infos[i].cu;
}
dw_offset_t DIEOffsetAtIndex(uint32_t i) const {
@@ -73,7 +73,7 @@ public:
protected:
struct AttributeValue {
- const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in
+ const DWARFUnit *cu; // Keep the compile unit with each attribute in
// case we have DW_FORM_ref_addr values
dw_offset_t die_offset;
DWARFAttribute attr;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
new file mode 100644
index 000000000000..077de9604f1d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
@@ -0,0 +1,193 @@
+//===-- DWARFBaseDIE.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFBaseDIE.h"
+
+#include "DWARFUnit.h"
+#include "DWARFDebugInfoEntry.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+using namespace lldb_private;
+
+DIERef DWARFBaseDIE::GetDIERef() const {
+ if (!IsValid())
+ return DIERef();
+
+ dw_offset_t cu_offset = m_cu->GetOffset();
+ if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
+ cu_offset = m_cu->GetBaseObjOffset();
+ return DIERef(cu_offset, m_die->GetOffset());
+}
+
+dw_tag_t DWARFBaseDIE::Tag() const {
+ if (m_die)
+ return m_die->Tag();
+ else
+ return 0;
+}
+
+const char *DWARFBaseDIE::GetTagAsCString() const {
+ return lldb_private::DW_TAG_value_to_name(Tag());
+}
+
+const char *DWARFBaseDIE::GetAttributeValueAsString(const dw_attr_t attr,
+ const char *fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t DWARFBaseDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr,
+ uint64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+int64_t DWARFBaseDIE::GetAttributeValueAsSigned(const dw_attr_t attr,
+ int64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t DWARFBaseDIE::GetAttributeValueAsReference(const dw_attr_t attr,
+ uint64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t DWARFBaseDIE::GetAttributeValueAsAddress(const dw_attr_t attr,
+ uint64_t fail_value) const {
+ if (IsValid())
+ return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr,
+ fail_value);
+ else
+ return fail_value;
+}
+
+lldb::user_id_t DWARFBaseDIE::GetID() const {
+ return GetDIERef().GetUID(GetDWARF());
+}
+
+const char *DWARFBaseDIE::GetName() const {
+ if (IsValid())
+ return m_die->GetName(GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+lldb::LanguageType DWARFBaseDIE::GetLanguage() const {
+ if (IsValid())
+ return m_cu->GetLanguageType();
+ else
+ return lldb::eLanguageTypeUnknown;
+}
+
+lldb::ModuleSP DWARFBaseDIE::GetModule() const {
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ return dwarf->GetObjectFile()->GetModule();
+ else
+ return lldb::ModuleSP();
+}
+
+lldb_private::CompileUnit *DWARFBaseDIE::GetLLDBCompileUnit() const {
+ if (IsValid())
+ return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
+ else
+ return nullptr;
+}
+
+dw_offset_t DWARFBaseDIE::GetOffset() const {
+ if (IsValid())
+ return m_die->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+dw_offset_t DWARFBaseDIE::GetCompileUnitRelativeOffset() const {
+ if (IsValid())
+ return m_die->GetOffset() - m_cu->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+SymbolFileDWARF *DWARFBaseDIE::GetDWARF() const {
+ if (m_cu)
+ return m_cu->GetSymbolFileDWARF();
+ else
+ return nullptr;
+}
+
+lldb_private::TypeSystem *DWARFBaseDIE::GetTypeSystem() const {
+ if (m_cu)
+ return m_cu->GetTypeSystem();
+ else
+ return nullptr;
+}
+
+DWARFASTParser *DWARFBaseDIE::GetDWARFParser() const {
+ lldb_private::TypeSystem *type_system = GetTypeSystem();
+ if (type_system)
+ return type_system->GetDWARFParser();
+ else
+ return nullptr;
+}
+
+bool DWARFBaseDIE::HasChildren() const {
+ return m_die && m_die->HasChildren();
+}
+
+bool DWARFBaseDIE::Supports_DW_AT_APPLE_objc_complete_type() const {
+ return IsValid() && GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
+}
+
+size_t DWARFBaseDIE::GetAttributes(DWARFAttributes &attributes,
+ uint32_t depth) const {
+ if (IsValid()) {
+ return m_die->GetAttributes(m_cu, m_cu->GetFixedFormSizes(), attributes,
+ depth);
+ }
+ if (depth == 0)
+ attributes.Clear();
+ return 0;
+}
+
+void DWARFBaseDIE::Dump(lldb_private::Stream *s,
+ const uint32_t recurse_depth) const {
+ if (s && IsValid())
+ m_die->Dump(GetDWARF(), GetCU(), *s, recurse_depth);
+}
+
+bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) {
+ return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
+}
+
+bool operator!=(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs) {
+ return !(lhs == rhs);
+}
+
+const DWARFDataExtractor &DWARFBaseDIE::GetData() const {
+ // Clients must check if this DIE is valid before calling this function.
+ assert(IsValid());
+ return m_cu->GetData();
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
new file mode 100644
index 000000000000..2163a027ffbc
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -0,0 +1,157 @@
+//===-- DWARFBaseDIE.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFBaseDIE_h_
+#define SymbolFileDWARF_DWARFBaseDIE_h_
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/lldb-types.h"
+
+struct DIERef;
+class DWARFASTParser;
+class DWARFAttributes;
+class DWARFUnit;
+class DWARFDebugInfoEntry;
+class DWARFDeclContext;
+class DWARFDIECollection;
+class SymbolFileDWARF;
+
+class DWARFBaseDIE {
+public:
+ DWARFBaseDIE() : m_cu(nullptr), m_die(nullptr) {}
+
+ DWARFBaseDIE(DWARFUnit *cu, DWARFDebugInfoEntry *die)
+ : m_cu(cu), m_die(die) {}
+
+ DWARFBaseDIE(const DWARFUnit *cu, DWARFDebugInfoEntry *die)
+ : m_cu(const_cast<DWARFUnit *>(cu)), m_die(die) {}
+
+ DWARFBaseDIE(DWARFUnit *cu, const DWARFDebugInfoEntry *die)
+ : m_cu(cu), m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+
+ DWARFBaseDIE(const DWARFUnit *cu, const DWARFDebugInfoEntry *die)
+ : m_cu(const_cast<DWARFUnit *>(cu)),
+ m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+ explicit operator bool() const { return IsValid(); }
+
+ bool IsValid() const { return m_cu && m_die; }
+
+ bool HasChildren() const;
+
+ bool Supports_DW_AT_APPLE_objc_complete_type() const;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ SymbolFileDWARF *GetDWARF() const;
+
+ DWARFUnit *GetCU() const { return m_cu; }
+
+ DWARFDebugInfoEntry *GetDIE() const { return m_die; }
+
+ DIERef GetDIERef() const;
+
+ lldb_private::TypeSystem *GetTypeSystem() const;
+
+ DWARFASTParser *GetDWARFParser() const;
+
+ void Set(DWARFUnit *cu, DWARFDebugInfoEntry *die) {
+ if (cu && die) {
+ m_cu = cu;
+ m_die = die;
+ } else {
+ Clear();
+ }
+ }
+
+ void Clear() {
+ m_cu = nullptr;
+ m_die = nullptr;
+ }
+
+ //----------------------------------------------------------------------
+ // Get the data that contains the attribute values for this DIE. Support
+ // for .debug_types means that any DIE can have its data either in the
+ // .debug_info or the .debug_types section; this method will return the
+ // correct section data.
+ //
+ // Clients must validate that this object is valid before calling this.
+ //----------------------------------------------------------------------
+ const lldb_private::DWARFDataExtractor &GetData() const;
+
+ //----------------------------------------------------------------------
+ // Accessing information about a DIE
+ //----------------------------------------------------------------------
+ dw_tag_t Tag() const;
+
+ const char *GetTagAsCString() const;
+
+ dw_offset_t GetOffset() const;
+
+ dw_offset_t GetCompileUnitRelativeOffset() const;
+
+ //----------------------------------------------------------------------
+ // Get the LLDB user ID for this DIE. This is often just the DIE offset,
+ // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if
+ // we are doing Darwin DWARF in .o file, or DWARF stand alone debug
+ // info.
+ //----------------------------------------------------------------------
+ lldb::user_id_t GetID() const;
+
+ const char *GetName() const;
+
+ lldb::LanguageType GetLanguage() const;
+
+ lldb::ModuleSP GetModule() const;
+
+ lldb_private::CompileUnit *GetLLDBCompileUnit() const;
+
+ //----------------------------------------------------------------------
+ // Getting attribute values from the DIE.
+ //
+ // GetAttributeValueAsXXX() functions should only be used if you are
+ // looking for one or two attributes on a DIE. If you are trying to
+ // parse all attributes, use GetAttributes (...) instead
+ //----------------------------------------------------------------------
+ const char *GetAttributeValueAsString(const dw_attr_t attr,
+ const char *fail_value) const;
+
+ uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr,
+ uint64_t fail_value) const;
+
+ int64_t GetAttributeValueAsSigned(const dw_attr_t attr,
+ int64_t fail_value) const;
+
+ uint64_t GetAttributeValueAsReference(const dw_attr_t attr,
+ uint64_t fail_value) const;
+
+ uint64_t GetAttributeValueAsAddress(const dw_attr_t attr,
+ uint64_t fail_value) const;
+
+ size_t GetAttributes(DWARFAttributes &attributes, uint32_t depth = 0) const;
+
+ //----------------------------------------------------------------------
+ // Pretty printing
+ //----------------------------------------------------------------------
+
+ void Dump(lldb_private::Stream *s, const uint32_t recurse_depth) const;
+
+protected:
+ DWARFUnit *m_cu;
+ DWARFDebugInfoEntry *m_die;
+};
+
+bool operator==(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs);
+bool operator!=(const DWARFBaseDIE &lhs, const DWARFBaseDIE &rhs);
+
+#endif // SymbolFileDWARF_DWARFBaseDIE_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 5d7b12067263..8541f1cfe1f6 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -9,48 +9,22 @@
#include "DWARFCompileUnit.h"
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
-#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Mangled.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Host/StringConvert.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/LineTable.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/StreamString.h"
-#include "lldb/Utility/Timer.h"
-
-#include "DWARFDIECollection.h"
-#include "DWARFDebugAbbrev.h"
-#include "DWARFDebugAranges.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFFormValue.h"
-#include "LogChannelDWARF.h"
-#include "NameToDIE.h"
#include "SymbolFileDWARF.h"
-#include "SymbolFileDWARFDebugMap.h"
-#include "SymbolFileDWARFDwo.h"
+#include "lldb/Utility/Stream.h"
using namespace lldb;
using namespace lldb_private;
-using namespace std;
extern int g_verbose;
DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data)
- : m_dwarf2Data(dwarf2Data) {}
+ : DWARFUnit(dwarf2Data) {}
-DWARFCompileUnit::~DWARFCompileUnit() {}
-
-DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
- lldb::offset_t *offset_ptr) {
- DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(dwarf2Data));
- // Out of memory?
- if (cu_sp.get() == NULL)
- return nullptr;
-
- const DWARFDataExtractor &debug_info = dwarf2Data->get_debug_info_data();
+DWARFUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
+ const DWARFDataExtractor &debug_info,
+ lldb::offset_t *offset_ptr) {
+ // std::make_shared would require the ctor to be public.
+ std::shared_ptr<DWARFCompileUnit> cu_sp(new DWARFCompileUnit(dwarf2Data));
cu_sp->m_offset = *offset_ptr;
@@ -83,259 +57,6 @@ DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
return nullptr;
}
-void DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) {
- if (m_die_array.size() > 1) {
- // std::vectors never get any smaller when resized to a smaller size,
- // or when clear() or erase() are called, the size will report that it
- // is smaller, but the memory allocated remains intact (call capacity()
- // to see this). So we need to create a temporary vector and swap the
- // contents which will cause just the internal pointers to be swapped
- // so that when "tmp_array" goes out of scope, it will destroy the
- // contents.
-
- // Save at least the compile unit DIE
- DWARFDebugInfoEntry::collection tmp_array;
- m_die_array.swap(tmp_array);
- if (keep_compile_unit_die)
- m_die_array.push_back(tmp_array.front());
- }
-
- if (m_dwo_symbol_file)
- m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die);
-}
-
-//----------------------------------------------------------------------
-// ParseCompileUnitDIEsIfNeeded
-//
-// Parses a compile unit and indexes its DIEs if it hasn't already been
-// done.
-//----------------------------------------------------------------------
-size_t DWARFCompileUnit::ExtractDIEsIfNeeded(bool cu_die_only) {
- const size_t initial_die_array_size = m_die_array.size();
- if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
- return 0; // Already parsed
-
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat,
- "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
- m_offset, cu_die_only);
-
- // Set the offset to that of the first DIE and calculate the start of the
- // next compilation unit header.
- lldb::offset_t offset = GetFirstDIEOffset();
- lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
-
- DWARFDebugInfoEntry die;
- // Keep a flat array of the DIE for binary lookup by DIE offset
- if (!cu_die_only) {
- Log *log(
- LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
- if (log) {
- m_dwarf2Data->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
- log, "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at "
- ".debug_info[0x%8.8x]",
- GetOffset());
- }
- }
-
- uint32_t depth = 0;
- // We are in our compile unit, parse starting at the offset
- // we were told to parse
- const DWARFDataExtractor &debug_info_data =
- m_dwarf2Data->get_debug_info_data();
- std::vector<uint32_t> die_index_stack;
- die_index_stack.reserve(32);
- die_index_stack.push_back(0);
- bool prev_die_had_children = false;
- DWARFFormValue::FixedFormSizes fixed_form_sizes =
- DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
- m_is_dwarf64);
- while (offset < next_cu_offset &&
- die.FastExtract(debug_info_data, this, fixed_form_sizes, &offset)) {
- // if (log)
- // log->Printf("0x%8.8x: %*.*s%s%s",
- // die.GetOffset(),
- // depth * 2, depth * 2, "",
- // DW_TAG_value_to_name (die.Tag()),
- // die.HasChildren() ? " *" : "");
-
- const bool null_die = die.IsNULL();
- if (depth == 0) {
- if (initial_die_array_size == 0)
- AddCompileUnitDIE(die);
- uint64_t base_addr = die.GetAttributeValueAsAddress(
- m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
- if (base_addr == LLDB_INVALID_ADDRESS)
- base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this,
- DW_AT_entry_pc, 0);
- SetBaseAddress(base_addr);
- if (cu_die_only)
- return 1;
- } else {
- if (null_die) {
- if (prev_die_had_children) {
- // This will only happen if a DIE says is has children
- // but all it contains is a NULL tag. Since we are removing
- // the NULL DIEs from the list (saves up to 25% in C++ code),
- // we need a way to let the DIE know that it actually doesn't
- // have children.
- if (!m_die_array.empty())
- m_die_array.back().SetEmptyChildren(true);
- }
- } else {
- die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]);
-
- if (die_index_stack.back())
- m_die_array[die_index_stack.back()].SetSiblingIndex(
- m_die_array.size() - die_index_stack.back());
-
- // Only push the DIE if it isn't a NULL DIE
- m_die_array.push_back(die);
- }
- }
-
- if (null_die) {
- // NULL DIE.
- if (!die_index_stack.empty())
- die_index_stack.pop_back();
-
- if (depth > 0)
- --depth;
- if (depth == 0)
- break; // We are done with this compile unit!
-
- prev_die_had_children = false;
- } else {
- die_index_stack.back() = m_die_array.size() - 1;
- // Normal DIE
- const bool die_has_children = die.HasChildren();
- if (die_has_children) {
- die_index_stack.push_back(0);
- ++depth;
- }
- prev_die_had_children = die_has_children;
- }
- }
-
- // Give a little bit of info if we encounter corrupt DWARF (our offset
- // should always terminate at or before the start of the next compilation
- // unit header).
- if (offset > next_cu_offset) {
- m_dwarf2Data->GetObjectFile()->GetModule()->ReportWarning(
- "DWARF compile unit extends beyond its bounds cu 0x%8.8x at "
- "0x%8.8" PRIx64 "\n",
- GetOffset(), offset);
- }
-
- // Since std::vector objects will double their size, we really need to
- // make a new array with the perfect size so we don't end up wasting
- // space. So here we copy and swap to make sure we don't have any extra
- // memory taken up.
-
- if (m_die_array.size() < m_die_array.capacity()) {
- DWARFDebugInfoEntry::collection exact_size_die_array(m_die_array.begin(),
- m_die_array.end());
- exact_size_die_array.swap(m_die_array);
- }
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log && log->GetVerbose()) {
- StreamString strm;
- Dump(&strm);
- if (m_die_array.empty())
- strm.Printf("error: no DIE for compile unit");
- else
- m_die_array[0].Dump(m_dwarf2Data, this, strm, UINT32_MAX);
- log->PutString(strm.GetString());
- }
-
- if (!m_dwo_symbol_file)
- return m_die_array.size();
-
- DWARFCompileUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
- size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only);
- return m_die_array.size() + dwo_die_count -
- 1; // We have 2 CU die, but we want to count it only as one
-}
-
-void DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry &die) {
- assert(m_die_array.empty() && "Compile unit DIE already added");
- AddDIE(die);
-
- const DWARFDebugInfoEntry &cu_die = m_die_array.front();
- std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
- m_dwarf2Data->GetDwoSymbolFileForCompileUnit(*this, cu_die);
- if (!dwo_symbol_file)
- return;
-
- DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
- if (!dwo_cu)
- return; // Can't fetch the compile unit from the dwo file.
-
- DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
- if (!dwo_cu_die.IsValid())
- return; // Can't fetch the compile unit DIE from the dwo file.
-
- uint64_t main_dwo_id = cu_die.GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_GNU_dwo_id, 0);
- uint64_t sub_dwo_id =
- dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0);
- if (main_dwo_id != sub_dwo_id)
- return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to
- // a differectn compilation.
-
- m_dwo_symbol_file = std::move(dwo_symbol_file);
-
- dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_GNU_addr_base, 0);
- dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_GNU_ranges_base, 0);
- dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset);
-}
-
-dw_offset_t DWARFCompileUnit::GetAbbrevOffset() const {
- return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
-}
-
-bool DWARFCompileUnit::Verify(Stream *s) const {
- const DWARFDataExtractor &debug_info = m_dwarf2Data->get_debug_info_data();
- bool valid_offset = debug_info.ValidOffset(m_offset);
- bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset() - 1);
- bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
- bool abbr_offset_OK =
- m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset());
- bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
- if (valid_offset && length_OK && version_OK && addr_size_OK &&
- abbr_offset_OK) {
- return true;
- } else {
- s->Printf(" 0x%8.8x: ", m_offset);
- DumpDataExtractor(m_dwarf2Data->get_debug_info_data(), s, m_offset,
- lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0,
- 0);
- s->EOL();
- if (valid_offset) {
- if (!length_OK)
- s->Printf(" The length (0x%8.8x) for this compile unit is too "
- "large for the .debug_info provided.\n",
- m_length);
- if (!version_OK)
- s->Printf(" The 16 bit compile unit header version is not "
- "supported.\n");
- if (!abbr_offset_OK)
- s->Printf(" The offset into the .debug_abbrev section (0x%8.8x) "
- "is not valid.\n",
- GetAbbrevOffset());
- if (!addr_size_OK)
- s->Printf(" The address size is unsupported: 0x%2.2x\n",
- m_addr_size);
- } else
- s->Printf(" The start offset of the compile unit header in the "
- ".debug_info is invalid.\n");
- }
- return false;
-}
-
void DWARFCompileUnit::Dump(Stream *s) const {
s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, "
"abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at "
@@ -344,768 +65,7 @@ void DWARFCompileUnit::Dump(Stream *s) const {
GetNextCompileUnitOffset());
}
-static uint8_t g_default_addr_size = 4;
-
-uint8_t DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit *cu) {
- if (cu)
- return cu->GetAddressByteSize();
- return DWARFCompileUnit::GetDefaultAddressSize();
-}
-
-bool DWARFCompileUnit::IsDWARF64(const DWARFCompileUnit *cu) {
- if (cu)
- return cu->IsDWARF64();
- return false;
-}
-
-uint8_t DWARFCompileUnit::GetDefaultAddressSize() {
- return g_default_addr_size;
-}
-
-void DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) {
- g_default_addr_size = addr_size;
-}
-
-lldb::user_id_t DWARFCompileUnit::GetID() const {
- dw_offset_t local_id =
- m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
- if (m_dwarf2Data)
- return DIERef(local_id, local_id).GetUID(m_dwarf2Data);
- else
- return local_id;
-}
-
-void DWARFCompileUnit::BuildAddressRangeTable(
- SymbolFileDWARF *dwarf2Data, DWARFDebugAranges *debug_aranges) {
- // This function is usually called if there in no .debug_aranges section
- // in order to produce a compile unit level set of address ranges that
- // is accurate.
-
- size_t num_debug_aranges = debug_aranges->GetNumRanges();
-
- // First get the compile unit DIE only and check if it has a DW_AT_ranges
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
-
- const dw_offset_t cu_offset = GetOffset();
- if (die) {
- DWARFRangeList ranges;
- const size_t num_ranges =
- die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false);
- if (num_ranges > 0) {
- // This compile unit has DW_AT_ranges, assume this is correct if it
- // is present since clang no longer makes .debug_aranges by default
- // and it emits DW_AT_ranges for DW_TAG_compile_units. GCC also does
- // this with recent GCC builds.
- for (size_t i = 0; i < num_ranges; ++i) {
- const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
- debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
- range.GetRangeEnd());
- }
-
- return; // We got all of our ranges from the DW_AT_ranges attribute
- }
- }
- // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
-
- // If the DIEs weren't parsed, then we don't want all dies for all compile
- // units
- // to stay loaded when they weren't needed. So we can end up parsing the DWARF
- // and then throwing them all away to keep memory usage down.
- const bool clear_dies = ExtractDIEsIfNeeded(false) > 1;
-
- die = DIEPtr();
- if (die)
- die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
-
- if (debug_aranges->GetNumRanges() == num_debug_aranges) {
- // We got nothing from the functions, maybe we have a line tables only
- // situation. Check the line tables and build the arange table from this.
- SymbolContext sc;
- sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this);
- if (sc.comp_unit) {
- SymbolFileDWARFDebugMap *debug_map_sym_file =
- m_dwarf2Data->GetDebugMapSymfile();
- if (debug_map_sym_file == NULL) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table) {
- LineTable::FileAddressRanges file_ranges;
- const bool append = true;
- const size_t num_ranges =
- line_table->GetContiguousFileAddressRanges(file_ranges, append);
- for (uint32_t idx = 0; idx < num_ranges; ++idx) {
- const LineTable::FileAddressRanges::Entry &range =
- file_ranges.GetEntryRef(idx);
- debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
- range.GetRangeEnd());
- }
- }
- } else
- debug_map_sym_file->AddOSOARanges(dwarf2Data, debug_aranges);
- }
- }
-
- if (debug_aranges->GetNumRanges() == num_debug_aranges) {
- // We got nothing from the functions, maybe we have a line tables only
- // situation. Check the line tables and build the arange table from this.
- SymbolContext sc;
- sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this);
- if (sc.comp_unit) {
- LineTable *line_table = sc.comp_unit->GetLineTable();
-
- if (line_table) {
- LineTable::FileAddressRanges file_ranges;
- const bool append = true;
- const size_t num_ranges =
- line_table->GetContiguousFileAddressRanges(file_ranges, append);
- for (uint32_t idx = 0; idx < num_ranges; ++idx) {
- const LineTable::FileAddressRanges::Entry &range =
- file_ranges.GetEntryRef(idx);
- debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(),
- range.GetRangeEnd());
- }
- }
- }
- }
-
- // Keep memory down by clearing DIEs if this generate function
- // caused them to be parsed
- if (clear_dies)
- ClearDIEs(true);
-}
-
-const DWARFDebugAranges &DWARFCompileUnit::GetFunctionAranges() {
- if (m_func_aranges_ap.get() == NULL) {
- m_func_aranges_ap.reset(new DWARFDebugAranges());
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
-
- if (log) {
- m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage(
- log, "DWARFCompileUnit::GetFunctionAranges() for compile unit at "
- ".debug_info[0x%8.8x]",
- GetOffset());
- }
- const DWARFDebugInfoEntry *die = DIEPtr();
- if (die)
- die->BuildFunctionAddressRangeTable(m_dwarf2Data, this,
- m_func_aranges_ap.get());
-
- if (m_dwo_symbol_file) {
- DWARFCompileUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
- const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr();
- if (dwo_die)
- dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu,
- m_func_aranges_ap.get());
- }
-
- const bool minimize = false;
- m_func_aranges_ap->Sort(minimize);
- }
- return *m_func_aranges_ap.get();
-}
-
-DWARFDIE
-DWARFCompileUnit::LookupAddress(const dw_addr_t address) {
- if (DIE()) {
- const DWARFDebugAranges &func_aranges = GetFunctionAranges();
-
- // Re-check the aranges auto pointer contents in case it was created above
- if (!func_aranges.IsEmpty())
- return GetDIE(func_aranges.FindAddress(address));
- }
- return DWARFDIE();
-}
-
-//----------------------------------------------------------------------
-// Compare function DWARFDebugAranges::Range structures
-//----------------------------------------------------------------------
-static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
- const dw_offset_t die_offset) {
- return die.GetOffset() < die_offset;
-}
-
-//----------------------------------------------------------------------
-// GetDIE()
-//
-// Get the DIE (Debug Information Entry) with the specified offset by
-// first checking if the DIE is contained within this compile unit and
-// grabbing the DIE from this compile unit. Otherwise we grab the DIE
-// from the DWARF file.
-//----------------------------------------------------------------------
-DWARFDIE
-DWARFCompileUnit::GetDIE(dw_offset_t die_offset) {
- if (die_offset != DW_INVALID_OFFSET) {
- if (m_dwo_symbol_file)
- return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset);
-
- if (ContainsDIEOffset(die_offset)) {
- ExtractDIEsIfNeeded(false);
- DWARFDebugInfoEntry::iterator end = m_die_array.end();
- DWARFDebugInfoEntry::iterator pos =
- lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset);
- if (pos != end) {
- if (die_offset == (*pos).GetOffset())
- return DWARFDIE(this, &(*pos));
- }
- } else {
- // Don't specify the compile unit offset as we don't know it because the
- // DIE belongs to
- // a different compile unit in the same symbol file.
- return m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset);
- }
- }
- return DWARFDIE(); // Not found
-}
-
-size_t DWARFCompileUnit::AppendDIEsWithTag(const dw_tag_t tag,
- DWARFDIECollection &dies,
- uint32_t depth) const {
- size_t old_size = dies.Size();
- DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
- for (pos = m_die_array.begin(); pos != end; ++pos) {
- if (pos->Tag() == tag)
- dies.Append(DWARFDIE(this, &(*pos)));
- }
-
- // Return the number of DIEs added to the collection
- return dies.Size() - old_size;
-}
-
-// void
-// DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx)
-//{
-// m_global_die_indexes.push_back (die_idx);
-//}
-//
-//
-// void
-// DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die)
-//{
-// // Indexes to all file level global and static variables
-// m_global_die_indexes;
-//
-// if (m_die_array.empty())
-// return;
-//
-// const DWARFDebugInfoEntry* first_die = &m_die_array[0];
-// const DWARFDebugInfoEntry* end = first_die + m_die_array.size();
-// if (first_die <= die && die < end)
-// m_global_die_indexes.push_back (die - first_die);
-//}
-
-void DWARFCompileUnit::Index(NameToDIE &func_basenames,
- NameToDIE &func_fullnames, NameToDIE &func_methods,
- NameToDIE &func_selectors,
- NameToDIE &objc_class_selectors,
- NameToDIE &globals, NameToDIE &types,
- NameToDIE &namespaces) {
- assert(!m_dwarf2Data->GetBaseCompileUnit() &&
- "DWARFCompileUnit associated with .dwo or .dwp "
- "should not be indexed directly");
-
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
-
- if (log) {
- m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage(
- log,
- "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]",
- GetOffset());
- }
-
- const LanguageType cu_language = GetLanguageType();
- DWARFFormValue::FixedFormSizes fixed_form_sizes =
- DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
- m_is_dwarf64);
-
- IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames,
- func_fullnames, func_methods, func_selectors,
- objc_class_selectors, globals, types, namespaces);
-
- SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile();
- if (dwo_symbol_file) {
- IndexPrivate(dwo_symbol_file->GetCompileUnit(), cu_language,
- fixed_form_sizes, GetOffset(), func_basenames, func_fullnames,
- func_methods, func_selectors, objc_class_selectors, globals,
- types, namespaces);
- }
-}
-
-void DWARFCompileUnit::IndexPrivate(
- DWARFCompileUnit *dwarf_cu, const LanguageType cu_language,
- const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
- const dw_offset_t cu_offset, NameToDIE &func_basenames,
- NameToDIE &func_fullnames, NameToDIE &func_methods,
- NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
- NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
- DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin();
- DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();
- for (pos = begin; pos != end; ++pos) {
- const DWARFDebugInfoEntry &die = *pos;
-
- const dw_tag_t tag = die.Tag();
-
- switch (tag) {
- case DW_TAG_array_type:
- case DW_TAG_base_type:
- case DW_TAG_class_type:
- case DW_TAG_constant:
- case DW_TAG_enumeration_type:
- case DW_TAG_inlined_subroutine:
- case DW_TAG_namespace:
- case DW_TAG_string_type:
- case DW_TAG_structure_type:
- case DW_TAG_subprogram:
- case DW_TAG_subroutine_type:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- case DW_TAG_unspecified_type:
- case DW_TAG_variable:
- break;
-
- default:
- continue;
- }
-
- DWARFAttributes attributes;
- const char *name = NULL;
- const char *mangled_cstr = NULL;
- bool is_declaration = false;
- // bool is_artificial = false;
- bool has_address = false;
- bool has_location_or_const_value = false;
- bool is_global_or_static_variable = false;
-
- DWARFFormValue specification_die_form;
- const size_t num_attributes =
- die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
- if (num_attributes > 0) {
- for (uint32_t i = 0; i < num_attributes; ++i) {
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- switch (attr) {
- case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- name = form_value.AsCString();
- break;
-
- case DW_AT_declaration:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- is_declaration = form_value.Unsigned() != 0;
- break;
-
- // case DW_AT_artificial:
- // if (attributes.ExtractFormValueAtIndex(i,
- // form_value))
- // is_artificial = form_value.Unsigned() != 0;
- // break;
-
- case DW_AT_MIPS_linkage_name:
- case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- mangled_cstr = form_value.AsCString();
- break;
-
- case DW_AT_low_pc:
- case DW_AT_high_pc:
- case DW_AT_ranges:
- has_address = true;
- break;
-
- case DW_AT_entry_pc:
- has_address = true;
- break;
-
- case DW_AT_location:
- case DW_AT_const_value:
- has_location_or_const_value = true;
- if (tag == DW_TAG_variable) {
- const DWARFDebugInfoEntry *parent_die = die.GetParent();
- while (parent_die != NULL) {
- switch (parent_die->Tag()) {
- case DW_TAG_subprogram:
- case DW_TAG_lexical_block:
- case DW_TAG_inlined_subroutine:
- // Even if this is a function level static, we don't add it. We
- // could theoretically
- // add these if we wanted to by introspecting into the
- // DW_AT_location and seeing
- // if the location describes a hard coded address, but we dont
- // want the performance
- // penalty of that right now.
- is_global_or_static_variable = false;
- // if
- // (attributes.ExtractFormValueAtIndex(dwarf2Data,
- // i, form_value))
- // {
- // // If we have valid block
- // data, then we have location
- // expression bytes
- // // that are fixed (not a
- // location list).
- // const uint8_t *block_data =
- // form_value.BlockData();
- // if (block_data)
- // {
- // uint32_t block_length =
- // form_value.Unsigned();
- // if (block_length == 1 +
- // attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
- // {
- // if (block_data[0] ==
- // DW_OP_addr)
- // add_die = true;
- // }
- // }
- // }
- parent_die = NULL; // Terminate the while loop.
- break;
-
- case DW_TAG_compile_unit:
- is_global_or_static_variable = true;
- parent_die = NULL; // Terminate the while loop.
- break;
-
- default:
- parent_die =
- parent_die->GetParent(); // Keep going in the while loop.
- break;
- }
- }
- }
- break;
-
- case DW_AT_specification:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- specification_die_form = form_value;
- break;
- }
- }
- }
-
- switch (tag) {
- case DW_TAG_subprogram:
- if (has_address) {
- if (name) {
- ObjCLanguage::MethodName objc_method(name, true);
- if (objc_method.IsValid(true)) {
- ConstString objc_class_name_with_category(
- objc_method.GetClassNameWithCategory());
- ConstString objc_selector_name(objc_method.GetSelector());
- ConstString objc_fullname_no_category_name(
- objc_method.GetFullNameWithoutCategory(true));
- ConstString objc_class_name_no_category(objc_method.GetClassName());
- func_fullnames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- if (objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_with_category,
- DIERef(cu_offset, die.GetOffset()));
- if (objc_class_name_no_category &&
- objc_class_name_no_category != objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_no_category,
- DIERef(cu_offset, die.GetOffset()));
- if (objc_selector_name)
- func_selectors.Insert(objc_selector_name,
- DIERef(cu_offset, die.GetOffset()));
- if (objc_fullname_no_category_name)
- func_fullnames.Insert(objc_fullname_no_category_name,
- DIERef(cu_offset, die.GetOffset()));
- }
- // If we have a mangled name, then the DW_AT_name attribute
- // is usually the method name without the class or any parameters
- const DWARFDebugInfoEntry *parent = die.GetParent();
- bool is_method = false;
- if (parent) {
- dw_tag_t parent_tag = parent->Tag();
- if (parent_tag == DW_TAG_class_type ||
- parent_tag == DW_TAG_structure_type) {
- is_method = true;
- } else {
- if (specification_die_form.IsValid()) {
- DWARFDIE specification_die =
- dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE(
- DIERef(specification_die_form));
- if (specification_die.GetParent().IsStructOrClass())
- is_method = true;
- }
- }
- }
-
- if (is_method)
- func_methods.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- else
- func_basenames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
-
- if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
- func_fullnames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- }
- if (mangled_cstr) {
- // Make sure our mangled name isn't the same string table entry
- // as our name. If it starts with '_', then it is ok, else compare
- // the string to make sure it isn't the same and we don't end up
- // with duplicate entries
- if (name && name != mangled_cstr &&
- ((mangled_cstr[0] == '_') ||
- (::strcmp(name, mangled_cstr) != 0))) {
- Mangled mangled(ConstString(mangled_cstr), true);
- func_fullnames.Insert(mangled.GetMangledName(),
- DIERef(cu_offset, die.GetOffset()));
- ConstString demangled = mangled.GetDemangledName(cu_language);
- if (demangled)
- func_fullnames.Insert(demangled,
- DIERef(cu_offset, die.GetOffset()));
- }
- }
- }
- break;
-
- case DW_TAG_inlined_subroutine:
- if (has_address) {
- if (name)
- func_basenames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- if (mangled_cstr) {
- // Make sure our mangled name isn't the same string table entry
- // as our name. If it starts with '_', then it is ok, else compare
- // the string to make sure it isn't the same and we don't end up
- // with duplicate entries
- if (name && name != mangled_cstr &&
- ((mangled_cstr[0] == '_') ||
- (::strcmp(name, mangled_cstr) != 0))) {
- Mangled mangled(ConstString(mangled_cstr), true);
- func_fullnames.Insert(mangled.GetMangledName(),
- DIERef(cu_offset, die.GetOffset()));
- ConstString demangled = mangled.GetDemangledName(cu_language);
- if (demangled)
- func_fullnames.Insert(demangled,
- DIERef(cu_offset, die.GetOffset()));
- }
- } else
- func_fullnames.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- }
- break;
-
- case DW_TAG_array_type:
- case DW_TAG_base_type:
- case DW_TAG_class_type:
- case DW_TAG_constant:
- case DW_TAG_enumeration_type:
- case DW_TAG_string_type:
- case DW_TAG_structure_type:
- case DW_TAG_subroutine_type:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- case DW_TAG_unspecified_type:
- if (name && !is_declaration)
- types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
- if (mangled_cstr && !is_declaration)
- types.Insert(ConstString(mangled_cstr),
- DIERef(cu_offset, die.GetOffset()));
- break;
-
- case DW_TAG_namespace:
- if (name)
- namespaces.Insert(ConstString(name),
- DIERef(cu_offset, die.GetOffset()));
- break;
-
- case DW_TAG_variable:
- if (name && has_location_or_const_value && is_global_or_static_variable) {
- globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
- // Be sure to include variables by their mangled and demangled
- // names if they have any since a variable can have a basename
- // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
- // mangled name "(anonymous namespace)::i"...
-
- // Make sure our mangled name isn't the same string table entry
- // as our name. If it starts with '_', then it is ok, else compare
- // the string to make sure it isn't the same and we don't end up
- // with duplicate entries
- if (mangled_cstr && name != mangled_cstr &&
- ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
- Mangled mangled(ConstString(mangled_cstr), true);
- globals.Insert(mangled.GetMangledName(),
- DIERef(cu_offset, die.GetOffset()));
- ConstString demangled = mangled.GetDemangledName(cu_language);
- if (demangled)
- globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
- }
- }
- break;
-
- default:
- continue;
- }
- }
-}
-
-bool DWARFCompileUnit::Supports_unnamed_objc_bitfields() {
- if (GetProducer() == eProducerClang) {
- const uint32_t major_version = GetProducerVersionMajor();
- if (major_version > 425 ||
- (major_version == 425 && GetProducerVersionUpdate() >= 13))
- return true;
- else
- return false;
- }
- return true; // Assume all other compilers didn't have incorrect ObjC bitfield
- // info
-}
-
-bool DWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type() {
- if (GetProducer() == eProducerLLVMGCC)
- return false;
- return true;
-}
-
-bool DWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid() {
- // llvm-gcc makes completely invalid decl file attributes and won't ever
- // be fixed, so we need to know to ignore these.
- return GetProducer() == eProducerLLVMGCC;
-}
-
-void DWARFCompileUnit::ParseProducerInfo() {
- m_producer_version_major = UINT32_MAX;
- m_producer_version_minor = UINT32_MAX;
- m_producer_version_update = UINT32_MAX;
-
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
- if (die) {
-
- const char *producer_cstr = die->GetAttributeValueAsString(
- m_dwarf2Data, this, DW_AT_producer, NULL);
- if (producer_cstr) {
- RegularExpression llvm_gcc_regex(
- llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple "
- "Inc\\. build [0-9]+\\) \\(LLVM build "
- "[\\.0-9]+\\)$"));
- if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) {
- m_producer = eProducerLLVMGCC;
- } else if (strstr(producer_cstr, "clang")) {
- static RegularExpression g_clang_version_regex(
- llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)"));
- RegularExpression::Match regex_match(3);
- if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr),
- &regex_match)) {
- std::string str;
- if (regex_match.GetMatchAtIndex(producer_cstr, 1, str))
- m_producer_version_major =
- StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
- if (regex_match.GetMatchAtIndex(producer_cstr, 2, str))
- m_producer_version_minor =
- StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
- if (regex_match.GetMatchAtIndex(producer_cstr, 3, str))
- m_producer_version_update =
- StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
- }
- m_producer = eProducerClang;
- } else if (strstr(producer_cstr, "GNU"))
- m_producer = eProducerGCC;
- }
- }
- if (m_producer == eProducerInvalid)
- m_producer = eProcucerOther;
-}
-
-DWARFCompileUnit::Producer DWARFCompileUnit::GetProducer() {
- if (m_producer == eProducerInvalid)
- ParseProducerInfo();
- return m_producer;
-}
-
-uint32_t DWARFCompileUnit::GetProducerVersionMajor() {
- if (m_producer_version_major == 0)
- ParseProducerInfo();
- return m_producer_version_major;
-}
-
-uint32_t DWARFCompileUnit::GetProducerVersionMinor() {
- if (m_producer_version_minor == 0)
- ParseProducerInfo();
- return m_producer_version_minor;
-}
-
-uint32_t DWARFCompileUnit::GetProducerVersionUpdate() {
- if (m_producer_version_update == 0)
- ParseProducerInfo();
- return m_producer_version_update;
-}
-
-LanguageType DWARFCompileUnit::LanguageTypeFromDWARF(uint64_t val) {
- // Note: user languages between lo_user and hi_user
- // must be handled explicitly here.
- switch (val) {
- case DW_LANG_Mips_Assembler:
- return eLanguageTypeMipsAssembler;
- case DW_LANG_GOOGLE_RenderScript:
- return eLanguageTypeExtRenderScript;
- default:
- return static_cast<LanguageType>(val);
- }
-}
-
-LanguageType DWARFCompileUnit::GetLanguageType() {
- if (m_language_type != eLanguageTypeUnknown)
- return m_language_type;
-
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
- if (die)
- m_language_type = LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(
- m_dwarf2Data, this, DW_AT_language, 0));
- return m_language_type;
-}
-
-bool DWARFCompileUnit::IsDWARF64() const { return m_is_dwarf64; }
-
-bool DWARFCompileUnit::GetIsOptimized() {
- if (m_is_optimized == eLazyBoolCalculate) {
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
- if (die) {
- m_is_optimized = eLazyBoolNo;
- if (die->GetAttributeValueAsUnsigned(m_dwarf2Data, this,
- DW_AT_APPLE_optimized, 0) == 1) {
- m_is_optimized = eLazyBoolYes;
- }
- }
- }
- if (m_is_optimized == eLazyBoolYes) {
- return true;
- } else {
- return false;
- }
-}
-
-DWARFFormValue::FixedFormSizes DWARFCompileUnit::GetFixedFormSizes() {
- return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
- IsDWARF64());
-}
-
-TypeSystem *DWARFCompileUnit::GetTypeSystem() {
- if (m_dwarf2Data)
- return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType());
- else
- return nullptr;
-}
-
-void DWARFCompileUnit::SetUserData(void *d) {
- m_user_data = d;
- if (m_dwo_symbol_file)
- m_dwo_symbol_file->GetCompileUnit()->SetUserData(d);
-}
-
-void DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base,
- dw_addr_t ranges_base,
- dw_offset_t base_obj_offset) {
- m_addr_base = addr_base;
- m_ranges_base = ranges_base;
- m_base_obj_offset = base_obj_offset;
-}
-lldb::ByteOrder DWARFCompileUnit::GetByteOrder() const {
- return m_dwarf2Data->GetObjectFile()->GetByteOrder();
+const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const {
+ return m_dwarf->get_debug_info_data();
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 8ea0d6465adf..9c1fc82f58b7 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -10,214 +10,39 @@
#ifndef SymbolFileDWARF_DWARFCompileUnit_h_
#define SymbolFileDWARF_DWARFCompileUnit_h_
-#include "DWARFDIE.h"
-#include "DWARFDebugInfoEntry.h"
-#include "lldb/lldb-enumerations.h"
+#include "DWARFUnit.h"
-class NameToDIE;
-class SymbolFileDWARF;
-class SymbolFileDWARFDwo;
+class DWARFCompileUnit : public DWARFUnit {
+ friend class DWARFUnit;
-typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
-
-class DWARFCompileUnit {
public:
- enum Producer {
- eProducerInvalid = 0,
- eProducerClang,
- eProducerGCC,
- eProducerLLVMGCC,
- eProcucerOther
- };
-
- static DWARFCompileUnitSP Extract(SymbolFileDWARF *dwarf2Data,
- lldb::offset_t *offset_ptr);
- ~DWARFCompileUnit();
-
- size_t ExtractDIEsIfNeeded(bool cu_die_only);
- DWARFDIE LookupAddress(const dw_addr_t address);
- size_t AppendDIEsWithTag(const dw_tag_t tag,
- DWARFDIECollection &matching_dies,
- uint32_t depth = UINT32_MAX) const;
- bool Verify(lldb_private::Stream *s) const;
- void Dump(lldb_private::Stream *s) const;
- // Offset of the initial length field.
- dw_offset_t GetOffset() const { return m_offset; }
- lldb::user_id_t GetID() const;
- // Size in bytes of the initial length + compile unit header.
- uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; }
- bool ContainsDIEOffset(dw_offset_t die_offset) const {
- return die_offset >= GetFirstDIEOffset() &&
- die_offset < GetNextCompileUnitOffset();
- }
- dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
- dw_offset_t GetNextCompileUnitOffset() const {
- return m_offset + (m_is_dwarf64 ? 12 : 4) + m_length;
+ static DWARFUnitSP Extract(SymbolFileDWARF *dwarf2Data,
+ const lldb_private::DWARFDataExtractor &debug_info,
+ lldb::offset_t *offset_ptr);
+ void Dump(lldb_private::Stream *s) const override;
+
+ //------------------------------------------------------------------
+ /// Get the data that contains the DIE information for this unit.
+ ///
+ /// @return
+ /// The correct data (.debug_types for DWARF 4 and earlier, and
+ /// .debug_info for DWARF 5 and later) for the DIE information in
+ /// this unit.
+ //------------------------------------------------------------------
+ const lldb_private::DWARFDataExtractor &GetData() const override;
+
+ //------------------------------------------------------------------
+ /// Get the size in bytes of the header.
+ ///
+ /// @return
+ /// Byte size of the compile unit header
+ //------------------------------------------------------------------
+ uint32_t GetHeaderByteSize() const override {
+ return m_is_dwarf64 ? 23 : 11;
}
- // Size of the CU data (without initial length and without header).
- size_t GetDebugInfoSize() const {
- return (m_is_dwarf64 ? 12 : 4) + m_length - Size();
- }
- // Size of the CU data incl. header but without initial length.
- uint32_t GetLength() const { return m_length; }
- uint16_t GetVersion() const { return m_version; }
- const DWARFAbbreviationDeclarationSet *GetAbbreviations() const {
- return m_abbrevs;
- }
- dw_offset_t GetAbbrevOffset() const;
- uint8_t GetAddressByteSize() const { return m_addr_size; }
- dw_addr_t GetBaseAddress() const { return m_base_addr; }
- dw_addr_t GetAddrBase() const { return m_addr_base; }
- dw_addr_t GetRangesBase() const { return m_ranges_base; }
- void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base, dw_offset_t base_obj_offset);
- void ClearDIEs(bool keep_compile_unit_die);
- void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
- DWARFDebugAranges *debug_aranges);
-
- lldb::ByteOrder GetByteOrder() const;
-
- lldb_private::TypeSystem *GetTypeSystem();
-
- DWARFFormValue::FixedFormSizes GetFixedFormSizes();
-
- void SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
-
- DWARFDIE
- GetCompileUnitDIEOnly() { return DWARFDIE(this, GetCompileUnitDIEPtrOnly()); }
-
- DWARFDIE
- DIE() { return DWARFDIE(this, DIEPtr()); }
-
- void AddDIE(DWARFDebugInfoEntry &die) {
- // The average bytes per DIE entry has been seen to be
- // around 14-20 so lets pre-reserve half of that since
- // we are now stripping the NULL tags.
-
- // Only reserve the memory if we are adding children of
- // the main compile unit DIE. The compile unit DIE is always
- // the first entry, so if our size is 1, then we are adding
- // the first compile unit child DIE and should reserve
- // the memory.
- if (m_die_array.empty())
- m_die_array.reserve(GetDebugInfoSize() / 24);
- m_die_array.push_back(die);
- }
-
- void AddCompileUnitDIE(DWARFDebugInfoEntry &die);
-
- bool HasDIEsParsed() const { return m_die_array.size() > 1; }
-
- DWARFDIE
- GetDIE(dw_offset_t die_offset);
-
- static uint8_t GetAddressByteSize(const DWARFCompileUnit *cu);
-
- static bool IsDWARF64(const DWARFCompileUnit *cu);
-
- static uint8_t GetDefaultAddressSize();
-
- static void SetDefaultAddressSize(uint8_t addr_size);
-
- void *GetUserData() const { return m_user_data; }
-
- void SetUserData(void *d);
-
- bool Supports_DW_AT_APPLE_objc_complete_type();
-
- bool DW_AT_decl_file_attributes_are_invalid();
-
- bool Supports_unnamed_objc_bitfields();
-
- void Index(NameToDIE &func_basenames, NameToDIE &func_fullnames,
- NameToDIE &func_methods, NameToDIE &func_selectors,
- NameToDIE &objc_class_selectors, NameToDIE &globals,
- NameToDIE &types, NameToDIE &namespaces);
-
- const DWARFDebugAranges &GetFunctionAranges();
-
- SymbolFileDWARF *GetSymbolFileDWARF() const { return m_dwarf2Data; }
-
- Producer GetProducer();
-
- uint32_t GetProducerVersionMajor();
-
- uint32_t GetProducerVersionMinor();
-
- uint32_t GetProducerVersionUpdate();
-
- static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
-
- lldb::LanguageType GetLanguageType();
-
- bool IsDWARF64() const;
-
- bool GetIsOptimized();
-
- SymbolFileDWARFDwo *GetDwoSymbolFile() const {
- return m_dwo_symbol_file.get();
- }
-
- dw_offset_t GetBaseObjOffset() const { return m_base_obj_offset; }
-
-protected:
- SymbolFileDWARF *m_dwarf2Data;
- std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
- const DWARFAbbreviationDeclarationSet *m_abbrevs;
- void *m_user_data = nullptr;
- DWARFDebugInfoEntry::collection
- m_die_array; // The compile unit debug information entry item
- std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap; // A table similar to
- // the .debug_aranges
- // table, but this one
- // points to the exact
- // DW_TAG_subprogram
- // DIEs
- dw_addr_t m_base_addr = 0;
- // Offset of the initial length field.
- dw_offset_t m_offset;
- dw_offset_t m_length;
- uint16_t m_version;
- uint8_t m_addr_size;
- Producer m_producer = eProducerInvalid;
- uint32_t m_producer_version_major = 0;
- uint32_t m_producer_version_minor = 0;
- uint32_t m_producer_version_update = 0;
- lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown;
- bool m_is_dwarf64;
- lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
- dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
- dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
- // If this is a dwo compile unit this is the offset of the base compile unit
- // in the main object file
- dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;
-
- void ParseProducerInfo();
-
- static void
- IndexPrivate(DWARFCompileUnit *dwarf_cu, const lldb::LanguageType cu_language,
- const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
- const dw_offset_t cu_offset, NameToDIE &func_basenames,
- NameToDIE &func_fullnames, NameToDIE &func_methods,
- NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
- NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces);
private:
DWARFCompileUnit(SymbolFileDWARF *dwarf2Data);
-
- const DWARFDebugInfoEntry *GetCompileUnitDIEPtrOnly() {
- ExtractDIEsIfNeeded(true);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
- }
-
- const DWARFDebugInfoEntry *DIEPtr() {
- ExtractDIEsIfNeeded(false);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
- }
-
DISALLOW_COPY_AND_ASSIGN(DWARFCompileUnit);
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 4ef2e772ea5d..d9754e911017 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -10,43 +10,27 @@
#include "DWARFDIE.h"
#include "DWARFASTParser.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIECollection.h"
-#include "DWARFDebugAbbrev.h"
-#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
-#include "DWARFDebugRanges.h"
#include "DWARFDeclContext.h"
-#include "DWARFFormValue.h"
-#include "SymbolFileDWARF.h"
-
-#include "lldb/Core/Module.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/TypeSystem.h"
+#include "DWARFUnit.h"
using namespace lldb_private;
-DIERef DWARFDIE::GetDIERef() const {
- if (!IsValid())
- return DIERef();
-
- dw_offset_t cu_offset = m_cu->GetOffset();
- if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
- cu_offset = m_cu->GetBaseObjOffset();
- return DIERef(cu_offset, m_die->GetOffset());
-}
+void DWARFDIE::ElaboratingDIEIterator::Next() {
+ assert(!m_worklist.empty() && "Incrementing end iterator?");
-dw_tag_t DWARFDIE::Tag() const {
- if (m_die)
- return m_die->Tag();
- else
- return 0;
-}
+ // Pop the current item from the list.
+ DWARFDIE die = m_worklist.back();
+ m_worklist.pop_back();
-const char *DWARFDIE::GetTagAsCString() const {
- return lldb_private::DW_TAG_value_to_name(Tag());
+ // And add back any items that elaborate it.
+ for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
+ if (DWARFDIE d = die.GetReferencedDIE(attr))
+ if (m_seen.insert(die.GetID()).second)
+ m_worklist.push_back(d);
+ }
}
DWARFDIE
@@ -91,37 +75,10 @@ DWARFDIE::GetDIE(dw_offset_t die_offset) const {
return DWARFDIE();
}
-const char *DWARFDIE::GetAttributeValueAsString(const dw_attr_t attr,
- const char *fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
-uint64_t DWARFDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr,
- uint64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
-int64_t DWARFDIE::GetAttributeValueAsSigned(const dw_attr_t attr,
- int64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
DWARFDIE
DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
if (IsValid()) {
- DWARFCompileUnit *cu = GetCU();
+ DWARFUnit *cu = GetCU();
SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF();
const bool check_specification_or_abstract_origin = true;
DWARFFormValue form_value;
@@ -132,29 +89,11 @@ DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
return DWARFDIE();
}
-uint64_t DWARFDIE::GetAttributeValueAsReference(const dw_attr_t attr,
- uint64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
-uint64_t DWARFDIE::GetAttributeValueAsAddress(const dw_attr_t attr,
- uint64_t fail_value) const {
- if (IsValid())
- return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr,
- fail_value);
- else
- return fail_value;
-}
-
DWARFDIE
DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
if (IsValid()) {
SymbolFileDWARF *dwarf = GetDWARF();
- DWARFCompileUnit *cu = GetCU();
+ DWARFUnit *cu = GetCU();
DWARFDebugInfoEntry *function_die = nullptr;
DWARFDebugInfoEntry *block_die = nullptr;
if (m_die->LookupAddress(file_addr, dwarf, cu, &function_die, &block_die)) {
@@ -171,17 +110,6 @@ DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
return DWARFDIE();
}
-lldb::user_id_t DWARFDIE::GetID() const {
- return GetDIERef().GetUID(GetDWARF());
-}
-
-const char *DWARFDIE::GetName() const {
- if (IsValid())
- return m_die->GetName(GetDWARF(), m_cu);
- else
- return nullptr;
-}
-
const char *DWARFDIE::GetMangledName() const {
if (IsValid())
return m_die->GetMangledName(GetDWARF(), m_cu);
@@ -203,28 +131,6 @@ const char *DWARFDIE::GetQualifiedName(std::string &storage) const {
return nullptr;
}
-lldb::LanguageType DWARFDIE::GetLanguage() const {
- if (IsValid())
- return m_cu->GetLanguageType();
- else
- return lldb::eLanguageTypeUnknown;
-}
-
-lldb::ModuleSP DWARFDIE::GetModule() const {
- SymbolFileDWARF *dwarf = GetDWARF();
- if (dwarf)
- return dwarf->GetObjectFile()->GetModule();
- else
- return lldb::ModuleSP();
-}
-
-lldb_private::CompileUnit *DWARFDIE::GetLLDBCompileUnit() const {
- if (IsValid())
- return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
- else
- return nullptr;
-}
-
lldb_private::Type *DWARFDIE::ResolveType() const {
if (IsValid())
return GetDWARF()->ResolveType(*this, true);
@@ -262,7 +168,7 @@ void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const {
void DWARFDIE::GetDWOContext(std::vector<CompilerContext> &context) const {
const dw_tag_t tag = Tag();
- if (tag == DW_TAG_compile_unit)
+ if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
return;
DWARFDIE parent = GetParent();
if (parent)
@@ -317,45 +223,17 @@ DWARFDIE::GetParentDeclContextDIE() const {
return DWARFDIE();
}
-dw_offset_t DWARFDIE::GetOffset() const {
- if (IsValid())
- return m_die->GetOffset();
- else
- return DW_INVALID_OFFSET;
-}
-
-dw_offset_t DWARFDIE::GetCompileUnitRelativeOffset() const {
- if (IsValid())
- return m_die->GetOffset() - m_cu->GetOffset();
- else
- return DW_INVALID_OFFSET;
-}
-
-SymbolFileDWARF *DWARFDIE::GetDWARF() const {
- if (m_cu)
- return m_cu->GetSymbolFileDWARF();
- else
- return nullptr;
-}
-
-lldb_private::TypeSystem *DWARFDIE::GetTypeSystem() const {
- if (m_cu)
- return m_cu->GetTypeSystem();
- else
- return nullptr;
-}
-
-DWARFASTParser *DWARFDIE::GetDWARFParser() const {
- lldb_private::TypeSystem *type_system = GetTypeSystem();
- if (type_system)
- return type_system->GetDWARFParser();
- else
- return nullptr;
+bool DWARFDIE::IsStructUnionOrClass() const {
+ const dw_tag_t tag = Tag();
+ return tag == DW_TAG_class_type || tag == DW_TAG_structure_type ||
+ tag == DW_TAG_union_type;
}
-bool DWARFDIE::IsStructOrClass() const {
- const dw_tag_t tag = Tag();
- return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
+bool DWARFDIE::IsMethod() const {
+ for (DWARFDIE d: elaborating_dies())
+ if (d.GetParent().IsStructUnionOrClass())
+ return true;
+ return false;
}
DWARFDIE
@@ -369,7 +247,7 @@ DWARFDIE::GetContainingDWOModuleDIE() const {
const dw_tag_t tag = parent.Tag();
if (tag == DW_TAG_module)
top_module_die = parent;
- else if (tag == DW_TAG_compile_unit)
+ else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
break;
}
@@ -391,25 +269,6 @@ lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const {
return lldb::ModuleSP();
}
-bool DWARFDIE::HasChildren() const {
- return m_die && m_die->HasChildren();
-}
-
-bool DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type() const {
- return IsValid() && GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
-}
-
-size_t DWARFDIE::GetAttributes(DWARFAttributes &attributes,
- uint32_t depth) const {
- if (IsValid()) {
- return m_die->GetAttributes(m_cu, m_cu->GetFixedFormSizes(), attributes,
- depth);
- }
- if (depth == 0)
- attributes.Clear();
- return 0;
-}
-
bool DWARFDIE::GetDIENamesAndRanges(
const char *&name, const char *&mangled, DWARFRangeList &ranges,
int &decl_file, int &decl_line, int &decl_column, int &call_file,
@@ -423,12 +282,6 @@ bool DWARFDIE::GetDIENamesAndRanges(
return false;
}
-void DWARFDIE::Dump(lldb_private::Stream *s,
- const uint32_t recurse_depth) const {
- if (s && IsValid())
- m_die->Dump(GetDWARF(), GetCU(), *s, recurse_depth);
-}
-
CompilerDecl DWARFDIE::GetDecl() const {
DWARFASTParser *dwarf_ast = GetDWARFParser();
if (dwarf_ast)
@@ -452,11 +305,3 @@ CompilerDeclContext DWARFDIE::GetContainingDeclContext() const {
else
return CompilerDeclContext();
}
-
-bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs) {
- return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
-}
-
-bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) {
- return !(lhs == rhs);
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index 8af3015b9d76..ecbf4912634e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -10,115 +10,41 @@
#ifndef SymbolFileDWARF_DWARFDIE_h_
#define SymbolFileDWARF_DWARFDIE_h_
-#include "lldb/Core/dwarf.h"
-#include "lldb/lldb-types.h"
-
-struct DIERef;
-class DWARFASTParser;
-class DWARFAttributes;
-class DWARFCompileUnit;
-class DWARFDebugInfoEntry;
-class DWARFDeclContext;
-class DWARFDIECollection;
-class SymbolFileDWARF;
-
-class DWARFDIE {
-public:
- DWARFDIE() : m_cu(nullptr), m_die(nullptr) {}
-
- DWARFDIE(DWARFCompileUnit *cu, DWARFDebugInfoEntry *die)
- : m_cu(cu), m_die(die) {}
-
- DWARFDIE(const DWARFCompileUnit *cu, DWARFDebugInfoEntry *die)
- : m_cu(const_cast<DWARFCompileUnit *>(cu)), m_die(die) {}
+#include "DWARFBaseDIE.h"
+#include "llvm/ADT/SmallSet.h"
- DWARFDIE(DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- : m_cu(cu), m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+class DWARFDIE : public DWARFBaseDIE {
+public:
+ class ElaboratingDIEIterator;
- DWARFDIE(const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- : m_cu(const_cast<DWARFCompileUnit *>(cu)),
- m_die(const_cast<DWARFDebugInfoEntry *>(die)) {}
+ using DWARFBaseDIE::DWARFBaseDIE;
//----------------------------------------------------------------------
// Tests
//----------------------------------------------------------------------
- explicit operator bool() const { return IsValid(); }
-
- bool IsValid() const { return m_cu && m_die; }
-
- bool IsStructOrClass() const;
+ bool IsStructUnionOrClass() const;
- bool HasChildren() const;
-
- bool Supports_DW_AT_APPLE_objc_complete_type() const;
+ bool IsMethod() const;
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
- SymbolFileDWARF *GetDWARF() const;
-
- DWARFCompileUnit *GetCU() const { return m_cu; }
-
- DWARFDebugInfoEntry *GetDIE() const { return m_die; }
-
- DIERef GetDIERef() const;
-
- lldb_private::TypeSystem *GetTypeSystem() const;
-
- DWARFASTParser *GetDWARFParser() const;
-
- void Set(DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) {
- if (cu && die) {
- m_cu = cu;
- m_die = die;
- } else {
- Clear();
- }
- }
-
- void Clear() {
- m_cu = nullptr;
- m_die = nullptr;
- }
-
lldb::ModuleSP GetContainingDWOModule() const;
DWARFDIE
GetContainingDWOModuleDIE() const;
- //----------------------------------------------------------------------
- // Accessing information about a DIE
- //----------------------------------------------------------------------
- dw_tag_t Tag() const;
-
- const char *GetTagAsCString() const;
-
- dw_offset_t GetOffset() const;
-
- dw_offset_t GetCompileUnitRelativeOffset() const;
+ inline llvm::iterator_range<ElaboratingDIEIterator> elaborating_dies() const;
//----------------------------------------------------------------------
- // Get the LLDB user ID for this DIE. This is often just the DIE offset,
- // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if
- // we are doing Darwin DWARF in .o file, or DWARF stand alone debug
- // info.
+ // Accessing information about a DIE
//----------------------------------------------------------------------
- lldb::user_id_t GetID() const;
-
- const char *GetName() const;
-
const char *GetMangledName() const;
const char *GetPubname() const;
const char *GetQualifiedName(std::string &storage) const;
- lldb::LanguageType GetLanguage() const;
-
- lldb::ModuleSP GetModule() const;
-
- lldb_private::CompileUnit *GetLLDBCompileUnit() const;
-
lldb_private::Type *ResolveType() const;
//----------------------------------------------------------------------
@@ -149,6 +75,7 @@ public:
//----------------------------------------------------------------------
DWARFDIE
GetDIE(dw_offset_t die_offset) const;
+ using DWARFBaseDIE::GetDIE;
DWARFDIE
LookupDeepestBlock(lldb::addr_t file_addr) const;
@@ -172,26 +99,9 @@ public:
// looking for one or two attributes on a DIE. If you are trying to
// parse all attributes, use GetAttributes (...) instead
//----------------------------------------------------------------------
- const char *GetAttributeValueAsString(const dw_attr_t attr,
- const char *fail_value) const;
-
- uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr,
- uint64_t fail_value) const;
-
- int64_t GetAttributeValueAsSigned(const dw_attr_t attr,
- int64_t fail_value) const;
-
- uint64_t GetAttributeValueAsReference(const dw_attr_t attr,
- uint64_t fail_value) const;
-
DWARFDIE
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;
- uint64_t GetAttributeValueAsAddress(const dw_attr_t attr,
- uint64_t fail_value) const;
-
- size_t GetAttributes(DWARFAttributes &attributes, uint32_t depth = 0) const;
-
bool GetDIENamesAndRanges(const char *&name, const char *&mangled,
DWARFRangeList &ranges, int &decl_file,
int &decl_line, int &decl_column, int &call_file,
@@ -199,23 +109,68 @@ public:
lldb_private::DWARFExpression *frame_base) const;
//----------------------------------------------------------------------
- // Pretty printing
+ // CompilerDecl related functions
//----------------------------------------------------------------------
- void Dump(lldb_private::Stream *s, const uint32_t recurse_depth) const;
-
lldb_private::CompilerDecl GetDecl() const;
lldb_private::CompilerDeclContext GetDeclContext() const;
lldb_private::CompilerDeclContext GetContainingDeclContext() const;
+};
+
+/// Iterate through all DIEs elaborating (i.e. reachable by a chain of
+/// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For
+/// convenience, the starting die is included in the sequence as the first
+/// item.
+class DWARFDIE::ElaboratingDIEIterator
+ : public std::iterator<std::input_iterator_tag, DWARFDIE> {
+
+ // The operating invariant is: top of m_worklist contains the "current" item
+ // and the rest of the list are items yet to be visited. An empty worklist
+ // means we've reached the end.
+ // Infinite recursion is prevented by maintaining a list of seen DIEs.
+ // Container sizes are optimized for the case of following DW_AT_specification
+ // and DW_AT_abstract_origin just once.
+ llvm::SmallVector<DWARFDIE, 2> m_worklist;
+ llvm::SmallSet<lldb::user_id_t, 3> m_seen;
+
+ void Next();
+
+public:
+ /// An iterator starting at die d.
+ explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
-protected:
- DWARFCompileUnit *m_cu;
- DWARFDebugInfoEntry *m_die;
+ /// End marker
+ ElaboratingDIEIterator() {}
+
+ const DWARFDIE &operator*() const { return m_worklist.back(); }
+ ElaboratingDIEIterator &operator++() {
+ Next();
+ return *this;
+ }
+ ElaboratingDIEIterator operator++(int) {
+ ElaboratingDIEIterator I = *this;
+ Next();
+ return I;
+ }
+
+ friend bool operator==(const ElaboratingDIEIterator &a,
+ const ElaboratingDIEIterator &b) {
+ if (a.m_worklist.empty() || b.m_worklist.empty())
+ return a.m_worklist.empty() == b.m_worklist.empty();
+ return a.m_worklist.back() == b.m_worklist.back();
+ }
+ friend bool operator!=(const ElaboratingDIEIterator &a,
+ const ElaboratingDIEIterator &b) {
+ return !(a == b);
+ }
};
-bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs);
-bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs);
+llvm::iterator_range<DWARFDIE::ElaboratingDIEIterator>
+DWARFDIE::elaborating_dies() const {
+ return llvm::make_range(ElaboratingDIEIterator(*this),
+ ElaboratingDIEIterator());
+}
#endif // SymbolFileDWARF_DWARFDIE_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
index 0c807d7d604b..2fcdd34d532f 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.cpp
@@ -22,6 +22,6 @@ DWARFDataExtractor::GetDWARFInitialLength(lldb::offset_t *offset_ptr) const {
dw_offset_t
DWARFDataExtractor::GetDWARFOffset(lldb::offset_t *offset_ptr) const {
- return GetMaxU64(offset_ptr, m_is_dwarf64 ? 8 : 4);
+ return GetMaxU64(offset_ptr, GetDWARFSizeOfOffset());
}
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
index 46d09f1ca237..ce0bfb3931d5 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -29,7 +29,7 @@ public:
dw_offset_t GetDWARFOffset(lldb::offset_t *offset_ptr) const;
size_t GetDWARFSizeofInitialLength() const { return m_is_dwarf64 ? 12 : 4; }
-
+ size_t GetDWARFSizeOfOffset() const { return m_is_dwarf64 ? 8 : 4; }
bool IsDWARF64() const { return m_is_dwarf64; }
protected:
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
index 1cf0e7eeeb60..affe4b85bdab 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
@@ -80,8 +80,8 @@ DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration(
//----------------------------------------------------------------------
// DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential()
//
-// Append an abbreviation declaration with a sequential code for O(n)
-// lookups. Handy when creating an DWARFAbbreviationDeclarationSet.
+// Append an abbreviation declaration with a sequential code for O(n) lookups.
+// Handy when creating an DWARFAbbreviationDeclarationSet.
//----------------------------------------------------------------------
dw_uleb128_t DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential(
const DWARFAbbreviationDeclaration &abbrevDecl) {
@@ -115,9 +115,9 @@ void DWARFAbbreviationDeclarationSet::GetUnsupportedForms(
//----------------------------------------------------------------------
// Encode
//
-// Encode the abbreviation table onto the end of the buffer provided
-// into a byte representation as would be found in a ".debug_abbrev"
-// debug information section.
+// Encode the abbreviation table onto the end of the buffer provided into a
+// byte representation as would be found in a ".debug_abbrev" debug information
+// section.
//----------------------------------------------------------------------
// void
// DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
index cecb69c8fb46..00265361f865 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -46,19 +46,17 @@ void DWARFDebugArangeSet::Compact() {
if (m_arange_descriptors.empty())
return;
- // Iterate through all arange descriptors and combine any ranges that
- // overlap or have matching boundaries. The m_arange_descriptors are assumed
- // to be in ascending order after being built by adding descriptors
- // using the AddDescriptor method.
+ // Iterate through all arange descriptors and combine any ranges that overlap
+ // or have matching boundaries. The m_arange_descriptors are assumed to be in
+ // ascending order after being built by adding descriptors using the
+ // AddDescriptor method.
uint32_t i = 0;
while (i + 1 < m_arange_descriptors.size()) {
if (m_arange_descriptors[i].end_address() >=
m_arange_descriptors[i + 1].address) {
// The current range ends at or exceeds the start of the next address
- // range.
- // Compute the max end address between the two and use that to make the
- // new
- // length.
+ // range. Compute the max end address between the two and use that to
+ // make the new length.
const dw_addr_t max_end_addr =
std::max(m_arange_descriptors[i].end_address(),
m_arange_descriptors[i + 1].end_address());
@@ -82,8 +80,8 @@ static bool DescriptorLessThan(const DWARFDebugArangeSet::Descriptor &range1,
}
//----------------------------------------------------------------------
-// Add a range descriptor and keep things sorted so we can easily
-// compact the ranges before being saved or used.
+// Add a range descriptor and keep things sorted so we can easily compact the
+// ranges before being saved or used.
//----------------------------------------------------------------------
void DWARFDebugArangeSet::AddDescriptor(
const DWARFDebugArangeSet::Descriptor &range) {
@@ -103,15 +101,14 @@ void DWARFDebugArangeSet::AddDescriptor(
// Non-contiguous entries, add this one before the found entry
m_arange_descriptors.insert(pos, range);
} else if (range_end_addr == pos->address) {
- // The top end of 'range' is the lower end of the entry
- // pointed to by 'pos'. We can combine range with the
- // entry we found by setting the starting address and
- // increasing the length since they don't overlap.
+ // The top end of 'range' is the lower end of the entry pointed to by
+ // 'pos'. We can combine range with the entry we found by setting the
+ // starting address and increasing the length since they don't overlap.
pos->address = range.address;
pos->length += range.length;
} else {
- // We can combine these two and make sure the largest end
- // address is used to make end address.
+ // We can combine these two and make sure the largest end address is
+ // used to make end address.
pos->address = range.address;
pos->length = std::max(found_end_addr, range_end_addr) - pos->address;
}
@@ -142,18 +139,18 @@ bool DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data,
// 7.20 Address Range Table
//
- // Each set of entries in the table of address ranges contained in
- // the .debug_aranges section begins with a header consisting of: a
- // 4-byte length containing the length of the set of entries for this
- // compilation unit, not including the length field itself; a 2-byte
- // version identifier containing the value 2 for DWARF Version 2; a
- // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
- // containing the size in bytes of an address (or the offset portion of
- // an address for segmented addressing) on the target system; and a
- // 1-byte unsigned integer containing the size in bytes of a segment
- // descriptor on the target system. This header is followed by a series
- // of tuples. Each tuple consists of an address and a length, each in
- // the size appropriate for an address on the target architecture.
+ // Each set of entries in the table of address ranges contained in the
+ // .debug_aranges section begins with a header consisting of: a 4-byte
+ // length containing the length of the set of entries for this compilation
+ // unit, not including the length field itself; a 2-byte version identifier
+ // containing the value 2 for DWARF Version 2; a 4-byte offset into
+ // the.debug_infosection; a 1-byte unsigned integer containing the size in
+ // bytes of an address (or the offset portion of an address for segmented
+ // addressing) on the target system; and a 1-byte unsigned integer
+ // containing the size in bytes of a segment descriptor on the target
+ // system. This header is followed by a series of tuples. Each tuple
+ // consists of an address and a length, each in the size appropriate for an
+ // address on the target architecture.
m_header.length = data.GetDWARFInitialLength(offset_ptr);
m_header.version = data.GetU16(offset_ptr);
m_header.cu_offset = data.GetDWARFOffset(offset_ptr);
@@ -195,8 +192,8 @@ bool DWARFDebugArangeSet::Extract(const DWARFDataExtractor &data,
arangeDescriptor.length =
data.GetMaxU64(offset_ptr, m_header.addr_size);
- // Each set of tuples is terminated by a 0 for the address and 0
- // for the length.
+ // Each set of tuples is terminated by a 0 for the address and 0 for
+ // the length.
if (arangeDescriptor.address || arangeDescriptor.length)
m_arange_descriptors.push_back(arangeDescriptor);
else
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
index 13c2d8726821..02f528d571b0 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -18,7 +18,7 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
#include "LogChannelDWARF.h"
#include "SymbolFileDWARF.h"
@@ -82,7 +82,7 @@ bool DWARFDebugAranges::Generate(SymbolFileDWARF *dwarf2Data) {
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
if (cu)
cu->BuildAddressRangeTable(dwarf2Data, this);
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 9c0f1d3c8905..dadc30dc918a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -72,7 +72,7 @@ DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
bool printed = false;
const size_t num_compile_units = GetNumCompileUnits();
for (size_t idx = 0; idx < num_compile_units; ++idx) {
- DWARFCompileUnit *cu = GetCompileUnitAtIndex(idx);
+ DWARFUnit *cu = GetCompileUnitAtIndex(idx);
dw_offset_t offset = cu->GetOffset();
if (cus_with_data.find(offset) == cus_with_data.end()) {
@@ -97,8 +97,10 @@ void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() {
if (m_compile_units.empty()) {
if (m_dwarf2Data != NULL) {
lldb::offset_t offset = 0;
- DWARFCompileUnitSP cu_sp;
- while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, &offset))) {
+ DWARFUnitSP cu_sp;
+ const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
+ while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data,
+ &offset))) {
m_compile_units.push_back(cu_sp);
offset = cu_sp->GetNextCompileUnitOffset();
@@ -112,16 +114,16 @@ size_t DWARFDebugInfo::GetNumCompileUnits() {
return m_compile_units.size();
}
-DWARFCompileUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) {
- DWARFCompileUnit *cu = NULL;
+DWARFUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) {
+ DWARFUnit *cu = NULL;
if (idx < GetNumCompileUnits())
cu = m_compile_units[idx].get();
return cu;
}
-bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const {
- // Not a verify efficient function, but it is handy for use in assertions
- // to make sure that a compile unit comes from a debug information file.
+bool DWARFDebugInfo::ContainsCompileUnit(const DWARFUnit *cu) const {
+ // Not a verify efficient function, but it is handy for use in assertions to
+ // make sure that a compile unit comes from a debug information file.
CompileUnitColl::const_iterator end_pos = m_compile_units.end();
CompileUnitColl::const_iterator pos;
@@ -133,13 +135,13 @@ bool DWARFDebugInfo::ContainsCompileUnit(const DWARFCompileUnit *cu) const {
}
bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset(
- dw_offset_t offset, const DWARFCompileUnitSP &cu_sp) {
+ dw_offset_t offset, const DWARFUnitSP &cu_sp) {
return offset < cu_sp->GetOffset();
}
-DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
+DWARFUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
uint32_t *idx_ptr) {
- DWARFCompileUnitSP cu_sp;
+ DWARFUnitSP cu_sp;
uint32_t cu_idx = DW_INVALID_INDEX;
if (cu_offset != DW_INVALID_OFFSET) {
ParseCompileUnitHeadersIfNeeded();
@@ -170,18 +172,18 @@ DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
return cu_sp.get();
}
-DWARFCompileUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) {
+DWARFUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) {
if (die_ref.cu_offset == DW_INVALID_OFFSET)
return GetCompileUnitContainingDIEOffset(die_ref.die_offset);
else
return GetCompileUnit(die_ref.cu_offset);
}
-DWARFCompileUnit *
+DWARFUnit *
DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) {
ParseCompileUnitHeadersIfNeeded();
- DWARFCompileUnitSP cu_sp;
+ DWARFUnitSP cu_sp;
// Watch out for single compile unit executable as they are pretty common
const size_t num_cus = m_compile_units.size();
@@ -205,7 +207,7 @@ DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) {
DWARFDIE
DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) {
- DWARFCompileUnit *cu = GetCompileUnitContainingDIEOffset(die_offset);
+ DWARFUnit *cu = GetCompileUnitContainingDIEOffset(die_offset);
if (cu)
return cu->GetDIE(die_offset);
return DWARFDIE();
@@ -218,275 +220,9 @@ DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) {
//----------------------------------------------------------------------
DWARFDIE
DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
- DWARFCompileUnit *cu = GetCompileUnit(die_ref);
+ DWARFUnit *cu = GetCompileUnit(die_ref);
if (cu)
return cu->GetDIE(die_ref.die_offset);
return DWARFDIE(); // Not found
}
-//----------------------------------------------------------------------
-// Parse
-//
-// Parses the .debug_info section and uses the .debug_abbrev section
-// and various other sections in the SymbolFileDWARF class and calls the
-// supplied callback function each time a compile unit header, or debug
-// information entry is successfully parsed. This function can be used
-// for different tasks such as parsing the file contents into a
-// structured data, dumping, verifying and much more.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Parse(SymbolFileDWARF *dwarf2Data, Callback callback,
- void *userData) {
- if (dwarf2Data) {
- lldb::offset_t offset = 0;
- uint32_t depth = 0;
- DWARFDebugInfoEntry die;
-
- DWARFCompileUnitSP cu;
- while ((cu = DWARFCompileUnit::Extract(dwarf2Data, &offset))) {
- const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
-
- depth = 0;
- // Call the callback function with no DIE pointer for the compile unit
- // and get the offset that we are to continue to parse from
- offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);
-
- // Make sure we are within our compile unit
- if (offset < next_cu_offset) {
- // We are in our compile unit, parse starting at the offset
- // we were told to parse
- bool done = false;
- while (!done && die.Extract(dwarf2Data, cu.get(), &offset)) {
- // Call the callback function with DIE pointer that falls within the
- // compile unit
- offset =
- callback(dwarf2Data, cu.get(), &die, offset, depth, userData);
-
- if (die.IsNULL()) {
- if (depth)
- --depth;
- else
- done = true; // We are done with this compile unit!
- } else if (die.HasChildren())
- ++depth;
- }
- }
-
- // Make sure the offset returned is valid, and if not stop parsing.
- // Returning DW_INVALID_OFFSET from this callback is a good way to end
- // all parsing
- if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
- break;
-
- // Make sure we start on a proper
- offset = next_cu_offset;
- }
- }
-}
-
-typedef struct DumpInfo {
- DumpInfo(Stream *init_strm, uint32_t off, uint32_t depth)
- : strm(init_strm), die_offset(off), recurse_depth(depth),
- found_depth(UINT32_MAX), found_die(false), ancestors() {}
- Stream *strm;
- const uint32_t die_offset;
- const uint32_t recurse_depth;
- uint32_t found_depth;
- bool found_die;
- std::vector<DWARFDebugInfoEntry> ancestors;
-
- DISALLOW_COPY_AND_ASSIGN(DumpInfo);
-} DumpInfo;
-
-//----------------------------------------------------------------------
-// DumpCallback
-//
-// A callback function for the static DWARFDebugInfo::Parse() function
-// that gets called each time a compile unit header or debug information
-// entry is successfully parsed.
-//
-// This function dump DWARF information and obey recurse depth and
-// whether a single DIE is to be dumped (or all of the data).
-//----------------------------------------------------------------------
-static dw_offset_t DumpCallback(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu, DWARFDebugInfoEntry *die,
- const dw_offset_t next_offset,
- const uint32_t curr_depth, void *userData) {
- DumpInfo *dumpInfo = (DumpInfo *)userData;
- Stream *s = dumpInfo->strm;
- bool show_parents =
- s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
-
- if (die) {
- // Are we dumping everything?
- if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
- // Yes we are dumping everything. Obey our recurse level though
- if (curr_depth < dumpInfo->recurse_depth)
- die->Dump(dwarf2Data, cu, *s, 0);
- } else {
- // We are dumping a specific DIE entry by offset
- if (dumpInfo->die_offset == die->GetOffset()) {
- // We found the DIE we were looking for, dump it!
- if (show_parents) {
- s->SetIndentLevel(0);
- const uint32_t num_ancestors = dumpInfo->ancestors.size();
- if (num_ancestors > 0) {
- for (uint32_t i = 0; i < num_ancestors - 1; ++i) {
- dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
- s->IndentMore();
- }
- }
- }
-
- dumpInfo->found_depth = curr_depth;
-
- die->Dump(dwarf2Data, cu, *s, 0);
-
- // Note that we found the DIE we were looking for
- dumpInfo->found_die = true;
-
- // Since we are dumping a single DIE, if there are no children we are
- // done!
- if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
- return DW_INVALID_OFFSET; // Return an invalid address to end parsing
- } else if (dumpInfo->found_die) {
- // Are we done with all the children?
- if (curr_depth <= dumpInfo->found_depth)
- return DW_INVALID_OFFSET;
-
- // We have already found our DIE and are printing it's children. Obey
- // our recurse depth and return an invalid offset if we get done
- // dumping all of the children
- if (dumpInfo->recurse_depth == UINT32_MAX ||
- curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
- die->Dump(dwarf2Data, cu, *s, 0);
- } else if (dumpInfo->die_offset > die->GetOffset()) {
- if (show_parents)
- dumpInfo->ancestors.back() = *die;
- }
- }
-
- // Keep up with our indent level
- if (die->IsNULL()) {
- if (show_parents)
- dumpInfo->ancestors.pop_back();
-
- if (curr_depth <= 1)
- return cu->GetNextCompileUnitOffset();
- else
- s->IndentLess();
- } else if (die->HasChildren()) {
- if (show_parents) {
- DWARFDebugInfoEntry null_die;
- dumpInfo->ancestors.push_back(null_die);
- }
- s->IndentMore();
- }
- } else {
- if (cu == NULL)
- s->PutCString("NULL - cu");
- // We have a compile unit, reset our indent level to zero just in case
- s->SetIndentLevel(0);
-
- // See if we are dumping everything?
- if (dumpInfo->die_offset == DW_INVALID_OFFSET) {
- // We are dumping everything
- if (cu) {
- cu->Dump(s);
- return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this
- // Compile Unit
- } else {
- return DW_INVALID_OFFSET;
- }
- } else {
- if (show_parents) {
- dumpInfo->ancestors.clear();
- dumpInfo->ancestors.resize(1);
- }
-
- // We are dumping only a single DIE possibly with it's children and
- // we must find it's compile unit before we can dump it properly
- if (cu && dumpInfo->die_offset < cu->GetFirstDIEOffset()) {
- // Not found, maybe the DIE offset provided wasn't correct?
- // *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << "
- // was not found." << endl;
- return DW_INVALID_OFFSET;
- } else {
- // See if the DIE is in this compile unit?
- if (cu && dumpInfo->die_offset < cu->GetNextCompileUnitOffset()) {
- return next_offset;
- // // We found our compile unit that contains our DIE, just skip to
- // dumping the requested DIE...
- // return dumpInfo->die_offset;
- } else {
- // Skip to the next compile unit as the DIE isn't in the current one!
- if (cu) {
- return cu->GetNextCompileUnitOffset();
- } else {
- return DW_INVALID_OFFSET;
- }
- }
- }
- }
- }
-
- // Just return the current offset to parse the next CU or DIE entry
- return next_offset;
-}
-
-//----------------------------------------------------------------------
-// Dump
-//
-// Dump the information in the .debug_info section to the specified
-// ostream. If die_offset is valid, a single DIE will be dumped. If the
-// die_offset is invalid, all the DWARF information will be dumped. Both
-// cases will obey a "recurse_depth" or how deep to traverse into the
-// children of each DIE entry. A recurse_depth of zero will dump all
-// compile unit headers. A recurse_depth of 1 will dump all compile unit
-// headers and the DW_TAG_compile unit tags. A depth of 2 will also
-// dump all types and functions.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Dump(Stream *s, SymbolFileDWARF *dwarf2Data,
- const uint32_t die_offset,
- const uint32_t recurse_depth) {
- DumpInfo dumpInfo(s, die_offset, recurse_depth);
- s->PutCString(".debug_info contents");
- if (dwarf2Data->get_debug_info_data().GetByteSize() > 0) {
- if (die_offset == DW_INVALID_OFFSET)
- s->PutCString(":\n");
- else {
- s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
- if (recurse_depth != UINT32_MAX)
- s->Printf(" recursing %u levels deep.", recurse_depth);
- s->EOL();
- }
- } else {
- s->PutCString(": < EMPTY >\n");
- return;
- }
- DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
-}
-
-//----------------------------------------------------------------------
-// Dump
-//
-// Dump the contents of this DWARFDebugInfo object as has been parsed
-// and/or modified after it has been parsed.
-//----------------------------------------------------------------------
-void DWARFDebugInfo::Dump(Stream *s, const uint32_t die_offset,
- const uint32_t recurse_depth) {
- DumpInfo dumpInfo(s, die_offset, recurse_depth);
-
- s->PutCString("Dumping .debug_info section from internal representation\n");
-
- CompileUnitColl::const_iterator pos;
- uint32_t curr_depth = 0;
- ParseCompileUnitHeadersIfNeeded();
- for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos) {
- DWARFCompileUnit *cu = pos->get();
- DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo);
-
- const DWARFDIE die = cu->DIE();
- if (die)
- die.Dump(s, recurse_depth);
- }
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index 14c7d767d05b..fc6085f99a21 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -13,6 +13,7 @@
#include <map>
#include <vector>
+#include "DWARFUnit.h"
#include "DWARFDIE.h"
#include "SymbolFileDWARF.h"
#include "lldb/Core/STLUtils.h"
@@ -26,7 +27,7 @@ typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
class DWARFDebugInfo {
public:
typedef dw_offset_t (*Callback)(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
DWARFDebugInfoEntry *die,
const dw_offset_t next_offset,
const uint32_t depth, void *userData);
@@ -35,22 +36,14 @@ public:
void SetDwarfData(SymbolFileDWARF *dwarf2Data);
size_t GetNumCompileUnits();
- bool ContainsCompileUnit(const DWARFCompileUnit *cu) const;
- DWARFCompileUnit *GetCompileUnitAtIndex(uint32_t idx);
- DWARFCompileUnit *GetCompileUnit(dw_offset_t cu_offset,
- uint32_t *idx_ptr = NULL);
- DWARFCompileUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset);
- DWARFCompileUnit *GetCompileUnit(const DIERef &die_ref);
+ bool ContainsCompileUnit(const DWARFUnit *cu) const;
+ DWARFUnit *GetCompileUnitAtIndex(uint32_t idx);
+ DWARFUnit *GetCompileUnit(dw_offset_t cu_offset, uint32_t *idx_ptr = NULL);
+ DWARFUnit *GetCompileUnitContainingDIEOffset(dw_offset_t die_offset);
+ DWARFUnit *GetCompileUnit(const DIERef &die_ref);
DWARFDIE GetDIEForDIEOffset(dw_offset_t die_offset);
DWARFDIE GetDIE(const DIERef &die_ref);
- void Dump(lldb_private::Stream *s, const uint32_t die_offset,
- const uint32_t recurse_depth);
- static void Parse(SymbolFileDWARF *parser, Callback callback, void *userData);
- static void Verify(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data);
- static void Dump(lldb_private::Stream *s, SymbolFileDWARF *dwarf2Data,
- const uint32_t die_offset, const uint32_t recurse_depth);
-
enum {
eDumpFlag_Verbose = (1 << 0), // Verbose dumping
eDumpFlag_ShowForm = (1 << 1), // Show the DW_form type
@@ -62,9 +55,9 @@ public:
protected:
static bool OffsetLessThanCompileUnitOffset(dw_offset_t offset,
- const DWARFCompileUnitSP &cu_sp);
+ const DWARFUnitSP &cu_sp);
- typedef std::vector<DWARFCompileUnitSP> CompileUnitColl;
+ typedef std::vector<DWARFUnitSP> CompileUnitColl;
//----------------------------------------------------------------------
// Member variables
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index f595bd83d846..d32aef6e162c 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -18,7 +18,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/Stream.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
@@ -34,7 +34,7 @@ using namespace std;
extern int g_verbose;
bool DWARFDebugInfoEntry::FastExtract(
- const DWARFDataExtractor &debug_info_data, const DWARFCompileUnit *cu,
+ const DWARFDataExtractor &debug_info_data, const DWARFUnit *cu,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
lldb::offset_t *offset_ptr) {
m_offset = *offset_ptr;
@@ -189,14 +189,14 @@ bool DWARFDebugInfoEntry::FastExtract(
//----------------------------------------------------------------------
// Extract
//
-// Extract a debug info entry for a given compile unit from the
-// .debug_info and .debug_abbrev data within the SymbolFileDWARF class
-// starting at the given offset
+// Extract a debug info entry for a given compile unit from the .debug_info and
+// .debug_abbrev data within the SymbolFileDWARF class starting at the given
+// offset
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
lldb::offset_t *offset_ptr) {
- const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
// const DWARFDataExtractor& debug_str_data =
// dwarf2Data->get_debug_str_data();
const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
@@ -218,9 +218,10 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
m_tag = abbrevDecl->Tag();
m_has_children = abbrevDecl->HasChildren();
- bool isCompileUnitTag = m_tag == DW_TAG_compile_unit;
+ bool isCompileUnitTag = (m_tag == DW_TAG_compile_unit ||
+ m_tag == DW_TAG_partial_unit);
if (cu && isCompileUnitTag)
- const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(0);
+ const_cast<DWARFUnit *>(cu)->SetBaseAddress(0);
// Skip all data in the .debug_info for the attributes
const uint32_t numAttributes = abbrevDecl->NumAttributes();
@@ -235,7 +236,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
DWARFFormValue form_value(cu, form);
if (form_value.ExtractValue(debug_info_data, &offset)) {
if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
- const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(
+ const_cast<DWARFUnit *>(cu)->SetBaseAddress(
form_value.Address());
}
} else {
@@ -245,8 +246,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
uint32_t form_size = 0;
switch (form) {
// Blocks if inlined data that have a length field and the data
- // bytes
- // inlined in the .debug_info
+ // bytes inlined in the .debug_info
case DW_FORM_exprloc:
case DW_FORM_block:
form_size = debug_info_data.GetULEB128(&offset);
@@ -356,11 +356,11 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// DumpAncestry
//
-// Dumps all of a debug information entries parents up until oldest and
-// all of it's attributes to the specified stream.
+// Dumps all of a debug information entries parents up until oldest and all of
+// it's attributes to the specified stream.
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const DWARFDebugInfoEntry *oldest,
Stream &s,
uint32_t recurse_depth) const {
@@ -374,11 +374,10 @@ void DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data,
// GetDIENamesAndRanges
//
// Gets the valid address ranges for a given DIE by looking for a
-// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges
-// attributes.
+// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, const char *&name,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, const char *&name,
const char *&mangled, DWARFRangeList &ranges, int &decl_file,
int &decl_line, int &decl_column, int &call_file, int &call_line,
int &call_column, DWARFExpression *frame_base) const {
@@ -404,8 +403,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
lldb::ModuleSP module = dwarf2Data->GetObjectFile()->GetModule();
if (abbrevDecl) {
- const DWARFDataExtractor &debug_info_data =
- dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
if (!debug_info_data.ValidOffset(offset))
return false;
@@ -451,9 +449,9 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
const DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
if (debug_ranges) {
debug_ranges->FindRanges(cu->GetRangesBase(), form_value.Unsigned(), ranges);
- // All DW_AT_ranges are relative to the base address of the
- // compile unit. We add the compile unit base address to make
- // sure all the addresses are properly fixed up.
+ // All DW_AT_ranges are relative to the base address of the compile
+ // unit. We add the compile unit base address to make sure all the
+ // addresses are properly fixed up.
ranges.Slide(cu->GetBaseAddress());
} else {
cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError(
@@ -582,13 +580,13 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
//----------------------------------------------------------------------
// Dump
//
-// Dumps a debug information entry and all of it's attributes to the
-// specified stream.
+// Dumps a debug information entry and all of it's attributes to the specified
+// stream.
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu, Stream &s,
+ const DWARFUnit *cu, Stream &s,
uint32_t recurse_depth) const {
- const DWARFDataExtractor &debug_info_data = dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
lldb::offset_t offset = m_offset;
if (debug_info_data.ValidOffset(offset)) {
@@ -639,8 +637,8 @@ void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data,
}
void DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu, Stream &s) const {
- const DWARFDIE cu_die = cu->GetCompileUnitDIEOnly();
+ DWARFUnit *cu, Stream &s) const {
+ const DWARFBaseDIE cu_die = cu->GetUnitDIEOnly();
const char *cu_name = NULL;
if (cu_die)
cu_name = cu_die.GetName();
@@ -658,12 +656,12 @@ void DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// DumpAttribute
//
-// Dumps a debug information entry attribute along with it's form. Any
-// special display of attributes is done (disassemble location lists,
-// show enumeration values for attributes, etc).
+// Dumps a debug information entry attribute along with it's form. Any special
+// display of attributes is done (disassemble location lists, show enumeration
+// values for attributes, etc).
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::DumpAttribute(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr,
Stream &s, dw_attr_t attr, dw_form_t form) {
bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
@@ -714,11 +712,10 @@ void DWARFDebugInfoEntry::DumpAttribute(
(*offset_ptr) - form_value.Unsigned(),
form_value.Unsigned());
DWARFExpression::PrintDWARFExpression(
- s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
+ s, locationData, DWARFUnit::GetAddressByteSize(cu), 4, false);
} else {
- // We have a location list offset as the value that is
- // the offset into the .debug_loc section that describes
- // the value over it's lifetime
+ // We have a location list offset as the value that is the offset into
+ // the .debug_loc section that describes the value over it's lifetime
uint64_t debug_loc_offset = form_value.Unsigned();
if (dwarf2Data) {
DWARFExpression::PrintDWARFLocationList(
@@ -759,18 +756,18 @@ void DWARFDebugInfoEntry::DumpAttribute(
//----------------------------------------------------------------------
// Get all attribute values for a given DIE, including following any
-// specification or abstract origin attributes and including those in
-// the results. Any duplicate attributes will have the first instance
-// take precedence (this can happen for declaration attributes).
+// specification or abstract origin attributes and including those in the
+// results. Any duplicate attributes will have the first instance take
+// precedence (this can happen for declaration attributes).
//----------------------------------------------------------------------
size_t DWARFDebugInfoEntry::GetAttributes(
- const DWARFCompileUnit *cu, DWARFFormValue::FixedFormSizes fixed_form_sizes,
+ const DWARFUnit *cu, DWARFFormValue::FixedFormSizes fixed_form_sizes,
DWARFAttributes &attributes, uint32_t curr_depth) const {
SymbolFileDWARF *dwarf2Data = nullptr;
const DWARFAbbreviationDeclaration *abbrevDecl = nullptr;
lldb::offset_t offset = 0;
if (cu) {
- if (m_tag != DW_TAG_compile_unit) {
+ if (m_tag != DW_TAG_compile_unit && m_tag != DW_TAG_partial_unit) {
SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
if (dwo_symbol_file)
return GetAttributes(dwo_symbol_file->GetCompileUnit(),
@@ -782,8 +779,7 @@ size_t DWARFDebugInfoEntry::GetAttributes(
}
if (abbrevDecl) {
- const DWARFDataExtractor &debug_info_data =
- dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
if (fixed_form_sizes.Empty())
fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(
@@ -803,9 +799,9 @@ size_t DWARFDebugInfoEntry::GetAttributes(
case DW_AT_sibling:
case DW_AT_declaration:
if (curr_depth > 0) {
- // This attribute doesn't make sense when combined with
- // the DIE that references this DIE. We know a DIE is
- // referencing this DIE because curr_depth is not zero
+ // This attribute doesn't make sense when combined with the DIE that
+ // references this DIE. We know a DIE is referencing this DIE because
+ // curr_depth is not zero
break;
}
LLVM_FALLTHROUGH;
@@ -819,7 +815,7 @@ size_t DWARFDebugInfoEntry::GetAttributes(
if (form_value.ExtractValue(debug_info_data, &offset)) {
dw_offset_t die_offset = form_value.Reference();
DWARFDIE spec_die =
- const_cast<DWARFCompileUnit *>(cu)->GetDIE(die_offset);
+ const_cast<DWARFUnit *>(cu)->GetDIE(die_offset);
if (spec_die)
spec_die.GetAttributes(attributes, curr_depth + 1);
}
@@ -841,17 +837,18 @@ size_t DWARFDebugInfoEntry::GetAttributes(
// GetAttributeValue
//
// Get the value of an attribute and return the .debug_info offset of the
-// attribute if it was properly extracted into form_value, or zero
-// if we fail since an offset of zero is invalid for an attribute (it
-// would be a compile unit header).
+// attribute if it was properly extracted into form_value, or zero if we fail
+// since an offset of zero is invalid for an attribute (it would be a compile
+// unit header).
//----------------------------------------------------------------------
dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, DWARFFormValue &form_value,
dw_offset_t *end_attr_offset_ptr,
bool check_specification_or_abstract_origin) const {
SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
- if (dwo_symbol_file && m_tag != DW_TAG_compile_unit)
+ if (dwo_symbol_file && m_tag != DW_TAG_compile_unit &&
+ m_tag != DW_TAG_partial_unit)
return GetAttributeValue(dwo_symbol_file, dwo_symbol_file->GetCompileUnit(),
attr, form_value, end_attr_offset_ptr,
check_specification_or_abstract_origin);
@@ -864,8 +861,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
if (attr_idx != DW_INVALID_INDEX) {
- const DWARFDataExtractor &debug_info_data =
- dwarf2Data->get_debug_info_data();
+ const DWARFDataExtractor &debug_info_data = cu->GetData();
uint32_t idx = 0;
while (idx < attr_idx)
@@ -886,7 +882,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
if (check_specification_or_abstract_origin) {
if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) {
DWARFDIE die =
- const_cast<DWARFCompileUnit *>(cu)->GetDIE(form_value.Reference());
+ const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference());
if (die) {
dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr,
@@ -898,7 +894,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) {
DWARFDIE die =
- const_cast<DWARFCompileUnit *>(cu)->GetDIE(form_value.Reference());
+ const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference());
if (die) {
dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr,
@@ -912,11 +908,11 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
if (!dwo_symbol_file)
return 0;
- DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
+ DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
if (!dwo_cu)
return 0;
- DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
+ DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
if (!dwo_cu_die.IsValid())
return 0;
@@ -928,13 +924,13 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
//----------------------------------------------------------------------
// GetAttributeValueAsString
//
-// Get the value of an attribute as a string return it. The resulting
-// pointer to the string data exists within the supplied SymbolFileDWARF
-// and will only be available as long as the SymbolFileDWARF is still around
-// and it's content doesn't change.
+// Get the value of an attribute as a string return it. The resulting pointer
+// to the string data exists within the supplied SymbolFileDWARF and will only
+// be available as long as the SymbolFileDWARF is still around and it's content
+// doesn't change.
//----------------------------------------------------------------------
const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, const char *fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -950,7 +946,7 @@ const char *DWARFDebugInfoEntry::GetAttributeValueAsString(
// Get the value of an attribute as unsigned and return it.
//----------------------------------------------------------------------
uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -966,7 +962,7 @@ uint64_t DWARFDebugInfoEntry::GetAttributeValueAsUnsigned(
// Get the value of an attribute a signed value and return it.
//----------------------------------------------------------------------
int64_t DWARFDebugInfoEntry::GetAttributeValueAsSigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, int64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -979,11 +975,11 @@ int64_t DWARFDebugInfoEntry::GetAttributeValueAsSigned(
//----------------------------------------------------------------------
// GetAttributeValueAsReference
//
-// Get the value of an attribute as reference and fix up and compile
-// unit relative offsets as needed.
+// Get the value of an attribute as reference and fix up and compile unit
+// relative offsets as needed.
//----------------------------------------------------------------------
uint64_t DWARFDebugInfoEntry::GetAttributeValueAsReference(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -994,7 +990,7 @@ uint64_t DWARFDebugInfoEntry::GetAttributeValueAsReference(
}
uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
@@ -1007,13 +1003,13 @@ uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
//----------------------------------------------------------------------
// GetAttributeHighPC
//
-// Get the hi_pc, adding hi_pc to lo_pc when specified
-// as an <offset-from-low-pc>.
+// Get the hi_pc, adding hi_pc to lo_pc when specified as an <offset-from-low-
+// pc>.
//
// Returns the hi_pc or fail_value.
//----------------------------------------------------------------------
dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t lo_pc,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t lo_pc,
uint64_t fail_value, bool check_specification_or_abstract_origin) const {
DWARFFormValue form_value;
if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr,
@@ -1031,13 +1027,13 @@ dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
//----------------------------------------------------------------------
// GetAttributeAddressRange
//
-// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified
-// as an <offset-from-low-pc>.
+// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified as an <offset-
+// from-low-pc>.
//
// Returns true or sets lo_pc and hi_pc to fail_value.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::GetAttributeAddressRange(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t &lo_pc,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t &lo_pc,
dw_addr_t &hi_pc, uint64_t fail_value,
bool check_specification_or_abstract_origin) const {
lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value,
@@ -1054,7 +1050,7 @@ bool DWARFDebugInfoEntry::GetAttributeAddressRange(
}
size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin) const {
ranges.Clear();
@@ -1083,23 +1079,23 @@ size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
//----------------------------------------------------------------------
// GetName
//
-// Get value of the DW_AT_name attribute and return it if one exists,
-// else return NULL.
+// Get value of the DW_AT_name attribute and return it if one exists, else
+// return NULL.
//----------------------------------------------------------------------
const char *DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const {
+ const DWARFUnit *cu) const {
return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
}
//----------------------------------------------------------------------
// GetMangledName
//
-// Get value of the DW_AT_MIPS_linkage_name attribute and return it if
-// one exists, else return the value of the DW_AT_name attribute
+// Get value of the DW_AT_MIPS_linkage_name attribute and return it if one
+// exists, else return the value of the DW_AT_name attribute
//----------------------------------------------------------------------
const char *
DWARFDebugInfoEntry::GetMangledName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
bool substitute_name_allowed) const {
const char *name = nullptr;
@@ -1123,11 +1119,11 @@ DWARFDebugInfoEntry::GetMangledName(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// GetPubname
//
-// Get value the name for a DIE as it should appear for a
-// .debug_pubnames or .debug_pubtypes section.
+// Get value the name for a DIE as it should appear for a .debug_pubnames or
+// .debug_pubtypes section.
//----------------------------------------------------------------------
const char *DWARFDebugInfoEntry::GetPubname(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const {
+ const DWARFUnit *cu) const {
const char *name = nullptr;
if (!dwarf2Data)
return name;
@@ -1149,14 +1145,13 @@ const char *DWARFDebugInfoEntry::GetPubname(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// GetName
//
-// Get value of the DW_AT_name attribute for a debug information entry
-// that exists at offset "die_offset" and place that value into the
-// supplied stream object. If the DIE is a NULL object "NULL" is placed
-// into the stream, and if no DW_AT_name attribute exists for the DIE
-// then nothing is printed.
+// Get value of the DW_AT_name attribute for a debug information entry that
+// exists at offset "die_offset" and place that value into the supplied stream
+// object. If the DIE is a NULL object "NULL" is placed into the stream, and if
+// no DW_AT_name attribute exists for the DIE then nothing is printed.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const dw_offset_t die_offset, Stream &s) {
if (dwarf2Data == NULL) {
s.PutCString("NULL");
@@ -1184,13 +1179,12 @@ bool DWARFDebugInfoEntry::GetName(SymbolFileDWARF *dwarf2Data,
//----------------------------------------------------------------------
// AppendTypeName
//
-// Follows the type name definition down through all needed tags to
-// end up with a fully qualified type name and dump the results to
-// the supplied stream. This is used to show the name of types given
-// a type identifier.
+// Follows the type name definition down through all needed tags to end up with
+// a fully qualified type name and dump the results to the supplied stream.
+// This is used to show the name of types given a type identifier.
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const dw_offset_t die_offset,
Stream &s) {
if (dwarf2Data == NULL) {
@@ -1318,7 +1312,7 @@ bool DWARFDebugInfoEntry::AppendTypeName(SymbolFileDWARF *dwarf2Data,
// BuildAddressRangeTable
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::BuildAddressRangeTable(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const {
if (m_tag) {
if (m_tag == DW_TAG_subprogram) {
@@ -1343,13 +1337,13 @@ void DWARFDebugInfoEntry::BuildAddressRangeTable(
//----------------------------------------------------------------------
// BuildFunctionAddressRangeTable
//
-// This function is very similar to the BuildAddressRangeTable function
-// except that the actual DIE offset for the function is placed in the
-// table instead of the compile unit offset (which is the way the
-// standard .debug_aranges section does it).
+// This function is very similar to the BuildAddressRangeTable function except
+// that the actual DIE offset for the function is placed in the table instead
+// of the compile unit offset (which is the way the standard .debug_aranges
+// section does it).
//----------------------------------------------------------------------
void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const {
if (m_tag) {
if (m_tag == DW_TAG_subprogram) {
@@ -1372,21 +1366,22 @@ void DWARFDebugInfoEntry::BuildFunctionAddressRangeTable(
}
void DWARFDebugInfoEntry::GetDeclContextDIEs(
- DWARFCompileUnit *cu, DWARFDIECollection &decl_context_dies) const {
+ DWARFUnit *cu, DWARFDIECollection &decl_context_dies) const {
DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
die.GetDeclContextDIEs(decl_context_dies);
}
void DWARFDebugInfoEntry::GetDWARFDeclContext(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
DWARFDeclContext &dwarf_decl_ctx) const {
const dw_tag_t tag = Tag();
- if (tag != DW_TAG_compile_unit) {
+ if (tag != DW_TAG_compile_unit && tag != DW_TAG_partial_unit) {
dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu));
DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE(dwarf2Data, cu);
if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this) {
- if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit)
+ if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit &&
+ parent_decl_ctx_die.Tag() != DW_TAG_partial_unit)
parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext(
parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(),
dwarf_decl_ctx);
@@ -1395,7 +1390,7 @@ void DWARFDebugInfoEntry::GetDWARFDeclContext(
}
bool DWARFDebugInfoEntry::MatchesDWARFDeclContext(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
const DWARFDeclContext &dwarf_decl_ctx) const {
DWARFDeclContext this_dwarf_decl_ctx;
@@ -1405,7 +1400,7 @@ bool DWARFDebugInfoEntry::MatchesDWARFDeclContext(
DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu) const {
+ DWARFUnit *cu) const {
DWARFAttributes attributes;
GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
return GetParentDeclContextDIE(dwarf2Data, cu, attributes);
@@ -1413,17 +1408,18 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
const DWARFAttributes &attributes) const {
DWARFDIE die(cu, const_cast<DWARFDebugInfoEntry *>(this));
while (die) {
- // If this is the original DIE that we are searching for a declaration
- // for, then don't look in the cache as we don't want our own decl
- // context to be our decl context...
+ // If this is the original DIE that we are searching for a declaration for,
+ // then don't look in the cache as we don't want our own decl context to be
+ // our decl context...
if (die.GetDIE() != this) {
switch (die.Tag()) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_union_type:
@@ -1465,7 +1461,7 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE(
}
const char *DWARFDebugInfoEntry::GetQualifiedName(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
std::string &storage) const {
DWARFAttributes attributes;
GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
@@ -1473,7 +1469,7 @@ const char *DWARFDebugInfoEntry::GetQualifiedName(SymbolFileDWARF *dwarf2Data,
}
const char *DWARFDebugInfoEntry::GetQualifiedName(
- SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
const DWARFAttributes &attributes, std::string &storage) const {
const char *name = GetName(dwarf2Data, cu);
@@ -1529,7 +1525,7 @@ const char *DWARFDebugInfoEntry::GetQualifiedName(
//----------------------------------------------------------------------
bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die) {
bool found_address = false;
@@ -1661,6 +1657,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
case DW_TAG_unspecified_type:
break;
case DW_TAG_partial_unit:
+ match_addr_range = true;
break;
case DW_TAG_imported_unit:
break;
@@ -1684,6 +1681,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
// puts("***MATCH***");
switch (m_tag) {
case DW_TAG_compile_unit: // File
+ case DW_TAG_partial_unit: // File
check_children = ((function_die != NULL) || (block_die != NULL));
break;
@@ -1706,10 +1704,12 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
break;
}
}
- } else { // compile units may not have a valid high/low pc when there
+ } else {
+ // Compile units may not have a valid high/low pc when there
// are address gaps in subroutines so we must always search
- // if there is no valid high and low PC
- check_children = (m_tag == DW_TAG_compile_unit) &&
+ // if there is no valid high and low PC.
+ check_children = (m_tag == DW_TAG_compile_unit ||
+ m_tag == DW_TAG_partial_unit) &&
((function_die != NULL) || (block_die != NULL));
}
} else {
@@ -1719,15 +1719,16 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
DWARFRangeList ranges;
DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
- // All DW_AT_ranges are relative to the base address of the
- // compile unit. We add the compile unit base address to make
- // sure all the addresses are properly fixed up.
+ // All DW_AT_ranges are relative to the base address of the compile
+ // unit. We add the compile unit base address to make sure all the
+ // addresses are properly fixed up.
ranges.Slide(cu->GetBaseAddress());
if (ranges.FindEntryThatContains(address)) {
found_address = true;
// puts("***MATCH***");
switch (m_tag) {
case DW_TAG_compile_unit: // File
+ case DW_TAG_partial_unit: // File
check_children = ((function_die != NULL) || (block_die != NULL));
break;
@@ -1772,7 +1773,7 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
const DWARFAbbreviationDeclaration *
DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
lldb::offset_t &offset) const {
if (dwarf2Data) {
offset = GetOffset();
@@ -1782,11 +1783,10 @@ DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(
const DWARFAbbreviationDeclaration *abbrev_decl =
abbrev_set->GetAbbreviationDeclaration(m_abbr_idx);
if (abbrev_decl) {
- // Make sure the abbreviation code still matches. If it doesn't and
- // the DWARF data was mmap'ed, the backing file might have been modified
+ // Make sure the abbreviation code still matches. If it doesn't and the
+ // DWARF data was mmap'ed, the backing file might have been modified
// which is bad news.
- const uint64_t abbrev_code =
- dwarf2Data->get_debug_info_data().GetULEB128(&offset);
+ const uint64_t abbrev_code = cu->GetData().GetULEB128(&offset);
if (abbrev_decl->Code() == abbrev_code)
return abbrev_decl;
@@ -1825,3 +1825,15 @@ void DWARFDebugInfoEntry::DumpDIECollection(
die_ref.HasChildren() ? " *" : "");
}
}
+
+bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
+ return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
+ m_sibling_idx == rhs.m_sibling_idx &&
+ m_empty_children == rhs.m_empty_children &&
+ m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
+ m_tag == rhs.m_tag;
+}
+
+bool DWARFDebugInfoEntry::operator!=(const DWARFDebugInfoEntry &rhs) const {
+ return !(*this == rhs);
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 89450d327adf..97cb3046eb3e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -60,128 +60,132 @@ public:
m_empty_children(false), m_abbr_idx(0), m_has_children(false),
m_tag(0) {}
+ explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; }
+ bool operator==(const DWARFDebugInfoEntry &rhs) const;
+ bool operator!=(const DWARFDebugInfoEntry &rhs) const;
+
void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const;
void BuildFunctionAddressRangeTable(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugAranges *debug_aranges) const;
bool FastExtract(const lldb_private::DWARFDataExtractor &debug_info_data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
lldb::offset_t *offset_ptr);
- bool Extract(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ bool Extract(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
lldb::offset_t *offset_ptr);
bool LookupAddress(const dw_addr_t address, SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die);
- size_t GetAttributes(const DWARFCompileUnit *cu,
+ size_t GetAttributes(const DWARFUnit *cu,
DWARFFormValue::FixedFormSizes fixed_form_sizes,
DWARFAttributes &attrs,
uint32_t curr_depth = 0)
const; // "curr_depth" for internal use only, don't set this yourself!!!
dw_offset_t
- GetAttributeValue(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ GetAttributeValue(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, DWARFFormValue &formValue,
dw_offset_t *end_attr_offset_ptr = nullptr,
bool check_specification_or_abstract_origin = false) const;
const char *GetAttributeValueAsString(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, const char *fail_value,
bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsUnsigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsReference(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
int64_t GetAttributeValueAsSigned(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, int64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsAddress(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_attr_t attr, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
dw_addr_t
- GetAttributeHighPC(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ GetAttributeHighPC(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
dw_addr_t lo_pc, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
bool GetAttributeAddressRange(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu, dw_addr_t &lo_pc,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, dw_addr_t &lo_pc,
dw_addr_t &hi_pc, uint64_t fail_value,
bool check_specification_or_abstract_origin = false) const;
size_t GetAttributeAddressRanges(
- SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin = false) const;
const char *GetName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const;
+ const DWARFUnit *cu) const;
const char *GetMangledName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
bool substitute_name_allowed = true) const;
const char *GetPubname(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu) const;
+ const DWARFUnit *cu) const;
- static bool GetName(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ static bool GetName(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const dw_offset_t die_offset, lldb_private::Stream &s);
static bool AppendTypeName(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
const dw_offset_t die_offset,
lldb_private::Stream &s);
const char *GetQualifiedName(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
std::string &storage) const;
const char *GetQualifiedName(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
const DWARFAttributes &attributes,
std::string &storage) const;
static bool OffsetLessThan(const DWARFDebugInfoEntry &a,
const DWARFDebugInfoEntry &b);
- void Dump(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ void Dump(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
lldb_private::Stream &s, uint32_t recurse_depth) const;
- void DumpAncestry(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ void DumpAncestry(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const DWARFDebugInfoEntry *oldest, lldb_private::Stream &s,
uint32_t recurse_depth) const;
static void
- DumpAttribute(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ DumpAttribute(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const lldb_private::DWARFDataExtractor &debug_info_data,
lldb::offset_t *offset_ptr, lldb_private::Stream &s,
dw_attr_t attr, dw_form_t form);
// This one dumps the comp unit name, objfile name and die offset for this die
// so the stream S.
- void DumpLocation(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ void DumpLocation(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
lldb_private::Stream &s) const;
bool
- GetDIENamesAndRanges(SymbolFileDWARF *dwarf2Data, const DWARFCompileUnit *cu,
+ GetDIENamesAndRanges(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const char *&name, const char *&mangled,
DWARFRangeList &rangeList, int &decl_file,
int &decl_line, int &decl_column, int &call_file,
@@ -190,7 +194,7 @@ public:
const DWARFAbbreviationDeclaration *
GetAbbreviationDeclarationPtr(SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit *cu,
+ const DWARFUnit *cu,
lldb::offset_t &offset) const;
dw_tag_t Tag() const { return m_tag; }
@@ -229,20 +233,20 @@ public:
return (HasChildren() && !m_empty_children) ? this + 1 : NULL;
}
- void GetDeclContextDIEs(DWARFCompileUnit *cu,
+ void GetDeclContextDIEs(DWARFUnit *cu,
DWARFDIECollection &decl_context_dies) const;
- void GetDWARFDeclContext(SymbolFileDWARF *dwarf2Data, DWARFCompileUnit *cu,
+ void GetDWARFDeclContext(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
DWARFDeclContext &dwarf_decl_ctx) const;
bool MatchesDWARFDeclContext(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
const DWARFDeclContext &dwarf_decl_ctx) const;
DWARFDIE GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu) const;
+ DWARFUnit *cu) const;
DWARFDIE GetParentDeclContextDIE(SymbolFileDWARF *dwarf2Data,
- DWARFCompileUnit *cu,
+ DWARFUnit *cu,
const DWARFAttributes &attributes) const;
void SetParent(DWARFDebugInfoEntry *parent) {
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 694d34fc211c..317ea4c22c66 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -242,8 +242,8 @@ dw_offset_t DWARFDebugLine::DumpStatementOpcodes(
log->Printf("0x%8.8x: DW_LNE_??? (%2.2x) - Skipping unknown upcode",
op_offset, opcode);
// Length doesn't include the zero opcode byte or the length itself,
- // but
- // it does include the sub_opcode, so we have to adjust for that below
+ // but it does include the sub_opcode, so we have to adjust for that
+ // below
offset += arg_size;
break;
}
@@ -324,9 +324,9 @@ dw_offset_t DWARFDebugLine::DumpStatementOpcodes(
// Special Opcodes
default:
if (opcode < prologue.opcode_base) {
- // We have an opcode that this parser doesn't know about, skip
- // the number of ULEB128 numbers that is says to skip in the
- // prologue's standard_opcode_lengths array
+ // We have an opcode that this parser doesn't know about, skip the
+ // number of ULEB128 numbers that is says to skip in the prologue's
+ // standard_opcode_lengths array
uint8_t n = prologue.standard_opcode_lengths[opcode - 1];
log->Printf("0x%8.8x: Special : Unknown skipping %u ULEB128 values.",
op_offset, n);
@@ -357,9 +357,9 @@ dw_offset_t DWARFDebugLine::DumpStatementOpcodes(
//----------------------------------------------------------------------
// Parse
//
-// Parse the entire line table contents calling callback each time a
-// new prologue is parsed and every time a new row is to be added to
-// the line table.
+// Parse the entire line table contents calling callback each time a new
+// prologue is parsed and every time a new row is to be added to the line
+// table.
//----------------------------------------------------------------------
void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data,
DWARFDebugLine::State::Callback callback,
@@ -444,7 +444,7 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
bool DWARFDebugLine::ParseSupportFiles(
const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data,
- const char *cu_comp_dir, dw_offset_t stmt_list,
+ const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list,
FileSpecList &support_files) {
lldb::offset_t offset = stmt_list;
@@ -463,7 +463,7 @@ bool DWARFDebugLine::ParseSupportFiles(
for (uint32_t file_idx = 1;
prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx) {
if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file))
- file_spec.SetFile(remapped_file, false);
+ file_spec.SetFile(remapped_file, false, FileSpec::Style::native);
support_files.Append(file_spec);
}
return true;
@@ -472,9 +472,9 @@ bool DWARFDebugLine::ParseSupportFiles(
//----------------------------------------------------------------------
// ParseStatementTable
//
-// Parse a single line table (prologue and all rows) and call the
-// callback function once for the prologue (row in state will be zero)
-// and each time a row is to be added to the line table.
+// Parse a single line table (prologue and all rows) and call the callback
+// function once for the prologue (row in state will be zero) and each time a
+// row is to be added to the line table.
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
@@ -511,8 +511,8 @@ bool DWARFDebugLine::ParseStatementTable(
uint8_t opcode = debug_line_data.GetU8(offset_ptr);
if (opcode == 0) {
- // Extended Opcodes always start with a zero opcode followed by
- // a uleb128 length so you can skip ones you don't know about
+ // Extended Opcodes always start with a zero opcode followed by a uleb128
+ // length so you can skip ones you don't know about
lldb::offset_t ext_offset = *offset_ptr;
dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr);
dw_offset_t arg_size = len - (*offset_ptr - ext_offset);
@@ -522,12 +522,12 @@ bool DWARFDebugLine::ParseStatementTable(
switch (sub_opcode) {
case DW_LNE_end_sequence:
// Set the end_sequence register of the state machine to true and
- // append a row to the matrix using the current values of the
- // state-machine registers. Then reset the registers to the initial
- // values specified above. Every statement program sequence must end
- // with a DW_LNE_end_sequence instruction which creates a row whose
- // address is that of the byte after the last target machine instruction
- // of the sequence.
+ // append a row to the matrix using the current values of the state-
+ // machine registers. Then reset the registers to the initial values
+ // specified above. Every statement program sequence must end with a
+ // DW_LNE_end_sequence instruction which creates a row whose address is
+ // that of the byte after the last target machine instruction of the
+ // sequence.
state.end_sequence = true;
state.AppendRowToMatrix(*offset_ptr);
state.Reset();
@@ -537,8 +537,8 @@ bool DWARFDebugLine::ParseStatementTable(
// Takes a single relocatable address as an operand. The size of the
// operand is the size appropriate to hold an address on the target
// machine. Set the address register to the value given by the
- // relocatable address. All of the other statement program opcodes
- // that affect the address register add a delta to it. This instruction
+ // relocatable address. All of the other statement program opcodes that
+ // affect the address register add a delta to it. This instruction
// stores a relocatable value into it instead.
if (arg_size == 4)
state.address = debug_line_data.GetU32(offset_ptr);
@@ -549,24 +549,24 @@ bool DWARFDebugLine::ParseStatementTable(
case DW_LNE_define_file:
// Takes 4 arguments. The first is a null terminated string containing
// a source file name. The second is an unsigned LEB128 number
- // representing
- // the directory index of the directory in which the file was found. The
- // third is an unsigned LEB128 number representing the time of last
- // modification of the file. The fourth is an unsigned LEB128 number
- // representing the length in bytes of the file. The time and length
- // fields may contain LEB128(0) if the information is not available.
+ // representing the directory index of the directory in which the file
+ // was found. The third is an unsigned LEB128 number representing the
+ // time of last modification of the file. The fourth is an unsigned
+ // LEB128 number representing the length in bytes of the file. The time
+ // and length fields may contain LEB128(0) if the information is not
+ // available.
//
// The directory index represents an entry in the include_directories
- // section of the statement program prologue. The index is LEB128(0)
- // if the file was found in the current directory of the compilation,
+ // section of the statement program prologue. The index is LEB128(0) if
+ // the file was found in the current directory of the compilation,
// LEB128(1) if it was found in the first directory in the
// include_directories section, and so on. The directory index is
// ignored for file names that represent full path names.
//
// The files are numbered, starting at 1, in the order in which they
- // appear; the names in the prologue come before names defined by
- // the DW_LNE_define_file instruction. These numbers are used in the
- // file register of the state machine.
+ // appear; the names in the prologue come before names defined by the
+ // DW_LNE_define_file instruction. These numbers are used in the file
+ // register of the state machine.
{
FileNameEntry fileEntry;
fileEntry.name = debug_line_data.GetCStr(offset_ptr);
@@ -578,8 +578,9 @@ bool DWARFDebugLine::ParseStatementTable(
break;
default:
- // Length doesn't include the zero opcode byte or the length itself, but
- // it does include the sub_opcode, so we have to adjust for that below
+ // Length doesn't include the zero opcode byte or the length itself,
+ // but it does include the sub_opcode, so we have to adjust for that
+ // below
(*offset_ptr) += arg_size;
break;
}
@@ -587,23 +588,23 @@ bool DWARFDebugLine::ParseStatementTable(
switch (opcode) {
// Standard Opcodes
case DW_LNS_copy:
- // Takes no arguments. Append a row to the matrix using the
- // current values of the state-machine registers. Then set
- // the basic_block register to false.
+ // Takes no arguments. Append a row to the matrix using the current
+ // values of the state-machine registers. Then set the basic_block
+ // register to false.
state.AppendRowToMatrix(*offset_ptr);
break;
case DW_LNS_advance_pc:
// Takes a single unsigned LEB128 operand, multiplies it by the
- // min_inst_length field of the prologue, and adds the
- // result to the address register of the state machine.
+ // min_inst_length field of the prologue, and adds the result to the
+ // address register of the state machine.
state.address +=
debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length;
break;
case DW_LNS_advance_line:
- // Takes a single signed LEB128 operand and adds that value to
- // the line register of the state machine.
+ // Takes a single signed LEB128 operand and adds that value to the line
+ // register of the state machine.
state.line += debug_line_data.GetSLEB128(offset_ptr);
break;
@@ -614,35 +615,35 @@ bool DWARFDebugLine::ParseStatementTable(
break;
case DW_LNS_set_column:
- // Takes a single unsigned LEB128 operand and stores it in the
- // column register of the state machine.
+ // Takes a single unsigned LEB128 operand and stores it in the column
+ // register of the state machine.
state.column = debug_line_data.GetULEB128(offset_ptr);
break;
case DW_LNS_negate_stmt:
- // Takes no arguments. Set the is_stmt register of the state
- // machine to the logical negation of its current value.
+ // Takes no arguments. Set the is_stmt register of the state machine to
+ // the logical negation of its current value.
state.is_stmt = !state.is_stmt;
break;
case DW_LNS_set_basic_block:
- // Takes no arguments. Set the basic_block register of the
- // state machine to true
+ // Takes no arguments. Set the basic_block register of the state
+ // machine to true
state.basic_block = true;
break;
case DW_LNS_const_add_pc:
- // Takes no arguments. Add to the address register of the state
- // machine the address increment value corresponding to special
- // opcode 255. The motivation for DW_LNS_const_add_pc is this:
- // when the statement program needs to advance the address by a
- // small amount, it can use a single special opcode, which occupies
- // a single byte. When it needs to advance the address by up to
- // twice the range of the last special opcode, it can use
- // DW_LNS_const_add_pc followed by a special opcode, for a total
- // of two bytes. Only if it needs to advance the address by more
- // than twice that range will it need to use both DW_LNS_advance_pc
- // and a special opcode, requiring three or more bytes.
+ // Takes no arguments. Add to the address register of the state machine
+ // the address increment value corresponding to special opcode 255. The
+ // motivation for DW_LNS_const_add_pc is this: when the statement
+ // program needs to advance the address by a small amount, it can use a
+ // single special opcode, which occupies a single byte. When it needs
+ // to advance the address by up to twice the range of the last special
+ // opcode, it can use DW_LNS_const_add_pc followed by a special opcode,
+ // for a total of two bytes. Only if it needs to advance the address by
+ // more than twice that range will it need to use both
+ // DW_LNS_advance_pc and a special opcode, requiring three or more
+ // bytes.
{
uint8_t adjust_opcode = 255 - prologue->opcode_base;
dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) *
@@ -652,40 +653,40 @@ bool DWARFDebugLine::ParseStatementTable(
break;
case DW_LNS_fixed_advance_pc:
- // Takes a single uhalf operand. Add to the address register of
- // the state machine the value of the (unencoded) operand. This
- // is the only extended opcode that takes an argument that is not
- // a variable length number. The motivation for DW_LNS_fixed_advance_pc
- // is this: existing assemblers cannot emit DW_LNS_advance_pc or
- // special opcodes because they cannot encode LEB128 numbers or
- // judge when the computation of a special opcode overflows and
- // requires the use of DW_LNS_advance_pc. Such assemblers, however,
- // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
+ // Takes a single uhalf operand. Add to the address register of the
+ // state machine the value of the (unencoded) operand. This is the only
+ // extended opcode that takes an argument that is not a variable length
+ // number. The motivation for DW_LNS_fixed_advance_pc is this: existing
+ // assemblers cannot emit DW_LNS_advance_pc or special opcodes because
+ // they cannot encode LEB128 numbers or judge when the computation of a
+ // special opcode overflows and requires the use of DW_LNS_advance_pc.
+ // Such assemblers, however, can use DW_LNS_fixed_advance_pc instead,
+ // sacrificing compression.
state.address += debug_line_data.GetU16(offset_ptr);
break;
case DW_LNS_set_prologue_end:
- // Takes no arguments. Set the prologue_end register of the
- // state machine to true
+ // Takes no arguments. Set the prologue_end register of the state
+ // machine to true
state.prologue_end = true;
break;
case DW_LNS_set_epilogue_begin:
- // Takes no arguments. Set the basic_block register of the
- // state machine to true
+ // Takes no arguments. Set the basic_block register of the state
+ // machine to true
state.epilogue_begin = true;
break;
case DW_LNS_set_isa:
- // Takes a single unsigned LEB128 operand and stores it in the
- // column register of the state machine.
+ // Takes a single unsigned LEB128 operand and stores it in the column
+ // register of the state machine.
state.isa = debug_line_data.GetULEB128(offset_ptr);
break;
default:
- // Handle any unknown standard opcodes here. We know the lengths
- // of such opcodes because they are specified in the prologue
- // as a multiple of LEB128 operands for each opcode.
+ // Handle any unknown standard opcodes here. We know the lengths of
+ // such opcodes because they are specified in the prologue as a
+ // multiple of LEB128 operands for each opcode.
{
uint8_t i;
assert(static_cast<size_t>(opcode - 1) <
@@ -702,32 +703,32 @@ bool DWARFDebugLine::ParseStatementTable(
// A special opcode value is chosen based on the amount that needs
// to be added to the line and address registers. The maximum line
- // increment for a special opcode is the value of the line_base
- // field in the header, plus the value of the line_range field,
- // minus 1 (line base + line range - 1). If the desired line
- // increment is greater than the maximum line increment, a standard
- // opcode must be used instead of a special opcode. The "address
- // advance" is calculated by dividing the desired address increment
- // by the minimum_instruction_length field from the header. The
- // special opcode is then calculated using the following formula:
+ // increment for a special opcode is the value of the line_base field in
+ // the header, plus the value of the line_range field, minus 1 (line base
+ // + line range - 1). If the desired line increment is greater than the
+ // maximum line increment, a standard opcode must be used instead of a
+ // special opcode. The "address advance" is calculated by dividing the
+ // desired address increment by the minimum_instruction_length field from
+ // the header. The special opcode is then calculated using the following
+ // formula:
//
// opcode = (desired line increment - line_base) + (line_range * address
// advance) + opcode_base
//
- // If the resulting opcode is greater than 255, a standard opcode
- // must be used instead.
+ // If the resulting opcode is greater than 255, a standard opcode must be
+ // used instead.
//
- // To decode a special opcode, subtract the opcode_base from the
- // opcode itself to give the adjusted opcode. The amount to
- // increment the address register is the result of the adjusted
- // opcode divided by the line_range multiplied by the
- // minimum_instruction_length field from the header. That is:
+ // To decode a special opcode, subtract the opcode_base from the opcode
+ // itself to give the adjusted opcode. The amount to increment the
+ // address register is the result of the adjusted opcode divided by the
+ // line_range multiplied by the minimum_instruction_length field from the
+ // header. That is:
//
// address increment = (adjusted opcode / line_range) *
// minimum_instruction_length
//
- // The amount to increment the line register is the line_base plus
- // the result of the adjusted opcode modulo the line_range. That is:
+ // The amount to increment the line register is the line_base plus the
+ // result of the adjusted opcode modulo the line_range. That is:
//
// line increment = line_base + (adjusted opcode % line_range)
@@ -755,8 +756,8 @@ static void ParseStatementTableCallback(dw_offset_t offset,
void *userData) {
DWARFDebugLine::LineTable *line_table = (DWARFDebugLine::LineTable *)userData;
if (state.row == DWARFDebugLine::State::StartParsingLineTable) {
- // Just started parsing the line table, so lets keep a reference to
- // the prologue using the supplied shared pointer
+ // Just started parsing the line table, so lets keep a reference to the
+ // prologue using the supplied shared pointer
line_table->prologue = state.prologue;
} else if (state.row == DWARFDebugLine::State::DoneParsingLineTable) {
// Done parsing line table, nothing to do for the cleanup
@@ -769,8 +770,8 @@ static void ParseStatementTableCallback(dw_offset_t offset,
//----------------------------------------------------------------------
// ParseStatementTable
//
-// Parse a line table at offset and populate the LineTable class with
-// the prologue and all rows.
+// Parse a line table at offset and populate the LineTable class with the
+// prologue and all rows.
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
@@ -861,11 +862,11 @@ void DWARFDebugLine::Prologue::Dump(Log *log) {
// buff.Append8(0); // Terminate the file names section with empty string
//}
-bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir,
- FileSpec &file) const {
+bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx,
+ const lldb_private::FileSpec &comp_dir, FileSpec &file) const {
uint32_t idx = file_idx - 1; // File indexes are 1 based...
if (idx < file_names.size()) {
- file.SetFile(file_names[idx].name, false);
+ file.SetFile(file_names[idx].name, false, FileSpec::Style::native);
if (file.IsRelative()) {
if (file_names[idx].dir_idx > 0) {
const uint32_t dir_idx = file_names[idx].dir_idx - 1;
@@ -876,7 +877,7 @@ bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir,
}
}
- if (comp_dir && comp_dir[0])
+ if (comp_dir)
file.PrependPathComponent(comp_dir);
}
return true;
@@ -936,11 +937,10 @@ uint32_t DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address,
if (address < cu_high_pc)
return rows.size() - 1;
} else {
- // Rely on fact that we are using a std::vector and we can do
- // pointer arithmetic to find the row index (which will be one less
- // that what we found since it will find the first position after
- // the current address) since std::vector iterators are just
- // pointers to the container type.
+ // Rely on fact that we are using a std::vector and we can do pointer
+ // arithmetic to find the row index (which will be one less that what we
+ // found since it will find the first position after the current address)
+ // since std::vector iterators are just pointers to the container type.
index = pos - begin_pos;
if (pos->address > address) {
if (index > 0)
@@ -1005,9 +1005,9 @@ static bool AddressLessThan(const DWARFDebugLine::Row &a,
return a.address < b.address;
}
-// Insert a row at the correct address if the addresses can be out of
-// order which can only happen when we are linking a line table that
-// may have had it's contents rearranged.
+// Insert a row at the correct address if the addresses can be out of order
+// which can only happen when we are linking a line table that may have had
+// it's contents rearranged.
void DWARFDebugLine::Row::Insert(Row::collection &state_coll,
const Row &state) {
// If we don't have anything yet, or if the address of the last state in our
@@ -1020,12 +1020,12 @@ void DWARFDebugLine::Row::Insert(Row::collection &state_coll,
state_coll.begin(), state_coll.end(), state, AddressLessThan));
// If the addresses are equal, we can safely replace the previous entry
- // with the current one if the one it is replacing is an end_sequence entry.
- // We currently always place an extra end sequence when ever we exit a valid
- // address range for a function in case the functions get rearranged by
- // optimizations or by order specifications. These extra end sequences will
- // disappear by getting replaced with valid consecutive entries within a
- // compile unit if there are no gaps.
+ // with the current one if the one it is replacing is an end_sequence
+ // entry. We currently always place an extra end sequence when ever we exit
+ // a valid address range for a function in case the functions get
+ // rearranged by optimizations or by order specifications. These extra end
+ // sequences will disappear by getting replaced with valid consecutive
+ // entries within a compile unit if there are no gaps.
if (range.first == range.second) {
state_coll.insert(range.first, state);
} else {
@@ -1065,10 +1065,9 @@ void DWARFDebugLine::State::Reset() { Row::Reset(prologue->default_is_stmt); }
// DWARFDebugLine::State::AppendRowToMatrix
//----------------------------------------------------------------------
void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) {
- // Each time we are to add an entry into the line table matrix
- // call the callback function so that someone can do something with
- // the current state of the state machine (like build a line table
- // or dump the line table!)
+ // Each time we are to add an entry into the line table matrix call the
+ // callback function so that someone can do something with the current state
+ // of the state machine (like build a line table or dump the line table!)
if (log) {
if (row == 0) {
log->PutCString("Address Line Column File ISA Flags");
@@ -1088,8 +1087,8 @@ void DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset) {
// DWARFDebugLine::State::Finalize
//----------------------------------------------------------------------
void DWARFDebugLine::State::Finalize(dw_offset_t offset) {
- // Call the callback with a special row state when we are done parsing a
- // line table
+ // Call the callback with a special row state when we are done parsing a line
+ // table
row = DoneParsingLineTable;
if (callback)
callback(offset, *this, callbackUserData);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index ea02cfed6e01..3ab15ac59028 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -90,7 +90,7 @@ public:
include_directories.clear();
file_names.clear();
}
- bool GetFile(uint32_t file_idx, const char *comp_dir,
+ bool GetFile(uint32_t file_idx, const lldb_private::FileSpec &cu_comp_dir,
lldb_private::FileSpec &file) const;
};
@@ -199,7 +199,8 @@ public:
static bool
ParseSupportFiles(const lldb::ModuleSP &module_sp,
const lldb_private::DWARFDataExtractor &debug_line_data,
- const char *cu_comp_dir, dw_offset_t stmt_list,
+ const lldb_private::FileSpec &cu_comp_dir,
+ dw_offset_t stmt_list,
lldb_private::FileSpecList &support_files);
static bool
ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
deleted file mode 100644
index 766899c497b0..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-//===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFDebugPubnames.h"
-
-#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/Timer.h"
-
-#include "DWARFCompileUnit.h"
-#include "DWARFDIECollection.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFFormValue.h"
-#include "LogChannelDWARF.h"
-#include "SymbolFileDWARF.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-DWARFDebugPubnames::DWARFDebugPubnames() : m_sets() {}
-
-bool DWARFDebugPubnames::Extract(const DWARFDataExtractor &data) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
- (uint64_t)data.GetByteSize());
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
- if (log)
- log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
- (uint64_t)data.GetByteSize());
-
- if (data.ValidOffset(0)) {
- lldb::offset_t offset = 0;
-
- DWARFDebugPubnamesSet set;
- while (data.ValidOffset(offset)) {
- if (set.Extract(data, &offset)) {
- m_sets.push_back(set);
- offset = set.GetOffsetOfNextEntry();
- } else
- break;
- }
- if (log)
- Dump(log);
- return true;
- }
- return false;
-}
-
-bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF *dwarf2Data) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat,
- "DWARFDebugPubnames::GeneratePubnames (data = %p)",
- static_cast<void *>(dwarf2Data));
-
- Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
- if (log)
- log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)",
- static_cast<void *>(dwarf2Data));
-
- m_sets.clear();
- DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
- if (debug_info) {
- uint32_t cu_idx = 0;
- const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
- for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
-
- DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
-
- DWARFFormValue::FixedFormSizes fixed_form_sizes =
- DWARFFormValue::GetFixedFormSizesForAddressSize(
- cu->GetAddressByteSize(), cu->IsDWARF64());
-
- bool clear_dies = cu->ExtractDIEsIfNeeded(false) > 1;
-
- DWARFDIECollection dies;
- const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_subprogram, dies) +
- cu->AppendDIEsWithTag(DW_TAG_variable, dies);
-
- dw_offset_t cu_offset = cu->GetOffset();
- DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
- cu->GetNextCompileUnitOffset() -
- cu_offset);
-
- size_t die_idx;
- for (die_idx = 0; die_idx < die_count; ++die_idx) {
- DWARFDIE die = dies.GetDIEAtIndex(die_idx);
- DWARFAttributes attributes;
- const char *name = NULL;
- const char *mangled = NULL;
- bool add_die = false;
- const size_t num_attributes = die.GetDIE()->GetAttributes(
- die.GetCU(), fixed_form_sizes, attributes);
- if (num_attributes > 0) {
- uint32_t i;
-
- dw_tag_t tag = die.Tag();
-
- for (i = 0; i < num_attributes; ++i) {
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- switch (attr) {
- case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- name = form_value.AsCString();
- break;
-
- case DW_AT_MIPS_linkage_name:
- case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(i, form_value))
- mangled = form_value.AsCString();
- break;
-
- case DW_AT_low_pc:
- case DW_AT_ranges:
- case DW_AT_entry_pc:
- if (tag == DW_TAG_subprogram)
- add_die = true;
- break;
-
- case DW_AT_location:
- if (tag == DW_TAG_variable) {
- DWARFDIE parent_die = die.GetParent();
- while (parent_die) {
- switch (parent_die.Tag()) {
- case DW_TAG_subprogram:
- case DW_TAG_lexical_block:
- case DW_TAG_inlined_subroutine:
- // Even if this is a function level static, we don't add it.
- // We could theoretically
- // add these if we wanted to by introspecting into the
- // DW_AT_location and seeing
- // if the location describes a hard coded address, but we
- // don't want the performance
- // penalty of that right now.
- add_die = false;
- parent_die.Clear(); // Terminate the while loop.
- break;
-
- case DW_TAG_compile_unit:
- add_die = true;
- parent_die.Clear(); // Terminate the while loop.
- break;
-
- default:
- parent_die =
- parent_die.GetParent(); // Keep going in the while loop.
- break;
- }
- }
- }
- break;
- }
- }
- }
-
- if (add_die && (name || mangled)) {
- pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(),
- mangled ? mangled : name);
- }
- }
-
- if (pubnames_set.NumDescriptors() > 0) {
- m_sets.push_back(pubnames_set);
- }
-
- // Keep memory down by clearing DIEs if this generate function
- // caused them to be parsed
- if (clear_dies)
- cu->ClearDIEs(true);
- }
- }
- if (m_sets.empty())
- return false;
- if (log)
- Dump(log);
- return true;
-}
-
-bool DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data) {
- m_sets.clear();
- DWARFDebugInfo *debug_info = dwarf2Data->DebugInfo();
- if (debug_info) {
- uint32_t cu_idx = 0;
- const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
- for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- DWARFDIECollection dies;
- const size_t die_count = cu->AppendDIEsWithTag(DW_TAG_base_type, dies);
- dw_offset_t cu_offset = cu->GetOffset();
- DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset,
- cu->GetNextCompileUnitOffset() -
- cu_offset);
-
- size_t die_idx;
- for (die_idx = 0; die_idx < die_count; ++die_idx) {
- DWARFDIE die = dies.GetDIEAtIndex(die_idx);
- const char *name = die.GetName();
-
- if (name)
- pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
- }
-
- if (pubnames_set.NumDescriptors() > 0) {
- m_sets.push_back(pubnames_set);
- }
- }
- }
- return !m_sets.empty();
-}
-
-void DWARFDebugPubnames::Dump(Log *s) const {
- if (m_sets.empty())
- s->PutCString("< EMPTY >\n");
- else {
- const_iterator pos;
- const_iterator end = m_sets.end();
-
- for (pos = m_sets.begin(); pos != end; ++pos)
- (*pos).Dump(s);
- }
-}
-
-bool DWARFDebugPubnames::Find(const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offsets) const {
- const_iterator pos;
- const_iterator end = m_sets.end();
-
- die_offsets.clear();
-
- for (pos = m_sets.begin(); pos != end; ++pos) {
- (*pos).Find(name, ignore_case, die_offsets);
- }
-
- return !die_offsets.empty();
-}
-
-bool DWARFDebugPubnames::Find(const RegularExpression &regex,
- std::vector<dw_offset_t> &die_offsets) const {
- const_iterator pos;
- const_iterator end = m_sets.end();
-
- die_offsets.clear();
-
- for (pos = m_sets.begin(); pos != end; ++pos) {
- (*pos).Find(regex, die_offsets);
- }
-
- return !die_offsets.empty();
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
deleted file mode 100644
index 57dabade012c..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===-- DWARFDebugPubnames.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFDebugPubnames_h_
-#define SymbolFileDWARF_DWARFDebugPubnames_h_
-
-#include "SymbolFileDWARF.h"
-
-#include <list>
-
-#include "DWARFDebugPubnamesSet.h"
-
-class DWARFDebugPubnames {
-public:
- DWARFDebugPubnames();
- bool Extract(const lldb_private::DWARFDataExtractor &data);
- bool GeneratePubnames(SymbolFileDWARF *dwarf2Data);
- bool GeneratePubBaseTypes(SymbolFileDWARF *dwarf2Data);
-
- void Dump(lldb_private::Log *s) const;
- bool Find(const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offset_coll) const;
- bool Find(const lldb_private::RegularExpression &regex,
- std::vector<dw_offset_t> &die_offsets) const;
-
-protected:
- typedef std::list<DWARFDebugPubnamesSet> collection;
- typedef collection::iterator iterator;
- typedef collection::const_iterator const_iterator;
-
- collection m_sets;
-};
-
-#endif // SymbolFileDWARF_DWARFDebugPubnames_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
deleted file mode 100644
index 21e2482783a1..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//===-- DWARFDebugPubnamesSet.cpp -------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFDebugPubnamesSet.h"
-
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/RegularExpression.h"
-
-#include "SymbolFileDWARF.h"
-
-using namespace lldb_private;
-
-DWARFDebugPubnamesSet::DWARFDebugPubnamesSet()
- : m_offset(DW_INVALID_OFFSET), m_header(), m_descriptors(),
- m_name_to_descriptor_index() {}
-
-DWARFDebugPubnamesSet::DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset,
- dw_offset_t cu_die_offset,
- dw_offset_t cu_die_length)
- : m_offset(debug_aranges_offset), m_header(), m_descriptors(),
- m_name_to_descriptor_index() {
- m_header.length =
- 10; // set the length to only include the header right for now
- m_header.version = 2; // The DWARF version number
- m_header.die_offset = cu_die_offset; // compile unit .debug_info offset
- m_header.die_length = cu_die_length; // compile unit .debug_info length
-}
-
-void DWARFDebugPubnamesSet::AddDescriptor(dw_offset_t cu_rel_offset,
- const char *name) {
- if (name && name[0]) {
- // Adjust our header length
- m_header.length += strlen(name) + 1 + sizeof(dw_offset_t);
- Descriptor pubnameDesc(cu_rel_offset, name);
- m_descriptors.push_back(pubnameDesc);
- }
-}
-
-void DWARFDebugPubnamesSet::Clear() {
- m_offset = DW_INVALID_OFFSET;
- m_header.length = 10;
- m_header.version = 2;
- m_header.die_offset = DW_INVALID_OFFSET;
- m_header.die_length = 0;
- m_descriptors.clear();
-}
-
-//----------------------------------------------------------------------
-// InitNameIndexes
-//----------------------------------------------------------------------
-void DWARFDebugPubnamesSet::InitNameIndexes() const {
- // Create the name index vector to be able to quickly search by name
- const size_t count = m_descriptors.size();
- for (uint32_t idx = 0; idx < count; ++idx) {
- const char *name = m_descriptors[idx].name.c_str();
- if (name && name[0])
- m_name_to_descriptor_index.insert(
- cstr_to_index_mmap::value_type(name, idx));
- }
-}
-
-bool DWARFDebugPubnamesSet::Extract(const DWARFDataExtractor &data,
- lldb::offset_t *offset_ptr) {
- if (data.ValidOffset(*offset_ptr)) {
- m_descriptors.clear();
- m_offset = *offset_ptr;
- m_header.length = data.GetDWARFInitialLength(offset_ptr);
- m_header.version = data.GetU16(offset_ptr);
- m_header.die_offset = data.GetDWARFOffset(offset_ptr);
- m_header.die_length = data.GetDWARFOffset(offset_ptr);
-
- Descriptor pubnameDesc;
- while (data.ValidOffset(*offset_ptr)) {
- pubnameDesc.offset = data.GetDWARFOffset(offset_ptr);
-
- if (pubnameDesc.offset) {
- const char *name = data.GetCStr(offset_ptr);
- if (name && name[0]) {
- pubnameDesc.name = name;
- m_descriptors.push_back(pubnameDesc);
- }
- } else
- break; // We are done if we get a zero 4 byte offset
- }
-
- return !m_descriptors.empty();
- }
- return false;
-}
-
-dw_offset_t DWARFDebugPubnamesSet::GetOffsetOfNextEntry() const {
- return m_offset + m_header.length + 4;
-}
-
-void DWARFDebugPubnamesSet::Dump(Log *log) const {
- log->Printf("Pubnames Header: length = 0x%8.8x, version = 0x%4.4x, "
- "die_offset = 0x%8.8x, die_length = 0x%8.8x",
- m_header.length, m_header.version, m_header.die_offset,
- m_header.die_length);
-
- bool verbose = log->GetVerbose();
-
- DescriptorConstIter pos;
- DescriptorConstIter end = m_descriptors.end();
- for (pos = m_descriptors.begin(); pos != end; ++pos) {
- if (verbose)
- log->Printf("0x%8.8x + 0x%8.8x = 0x%8.8x: %s", pos->offset,
- m_header.die_offset, pos->offset + m_header.die_offset,
- pos->name.c_str());
- else
- log->Printf("0x%8.8x: %s", pos->offset + m_header.die_offset,
- pos->name.c_str());
- }
-}
-
-void DWARFDebugPubnamesSet::Find(
- const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offset_coll) const {
- if (!m_descriptors.empty() && m_name_to_descriptor_index.empty())
- InitNameIndexes();
-
- std::pair<cstr_to_index_mmap::const_iterator,
- cstr_to_index_mmap::const_iterator>
- range(m_name_to_descriptor_index.equal_range(name));
- for (cstr_to_index_mmap::const_iterator pos = range.first;
- pos != range.second; ++pos)
- die_offset_coll.push_back(m_header.die_offset +
- m_descriptors[(*pos).second].offset);
-}
-
-void DWARFDebugPubnamesSet::Find(
- const RegularExpression &regex,
- std::vector<dw_offset_t> &die_offset_coll) const {
- DescriptorConstIter pos;
- DescriptorConstIter end = m_descriptors.end();
- for (pos = m_descriptors.begin(); pos != end; ++pos) {
- if (regex.Execute(pos->name))
- die_offset_coll.push_back(m_header.die_offset + pos->offset);
- }
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
deleted file mode 100644
index 6e7d3f38aa85..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//===-- DWARFDebugPubnamesSet.h ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFDebugPubnamesSet_h_
-#define SymbolFileDWARF_DWARFDebugPubnamesSet_h_
-
-#include "SymbolFileDWARF.h"
-#include <map>
-#include <string>
-#include <vector>
-#if __cplusplus >= 201103L || defined(_MSC_VER)
-#include <unordered_map>
-#else
-#include <ext/hash_map>
-#endif
-
-#include "lldb/Core/STLUtils.h"
-
-class DWARFDebugPubnamesSet {
-public:
- struct Header {
- uint32_t length; // length of the set of entries for this compilation unit,
- // not including the length field itself
- uint16_t version; // The DWARF version number
- uint32_t die_offset; // compile unit .debug_info offset
- uint32_t die_length; // compile unit .debug_info length
- Header()
- : length(10), version(2), die_offset(DW_INVALID_OFFSET), die_length(0) {
- }
- };
-
- struct Descriptor {
- Descriptor() : offset(), name() {}
-
- Descriptor(dw_offset_t the_offset, const char *the_name)
- : offset(the_offset), name(the_name ? the_name : "") {}
-
- dw_offset_t offset;
- std::string name;
- };
-
- DWARFDebugPubnamesSet();
- DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset,
- dw_offset_t cu_die_offset, dw_offset_t die_length);
- dw_offset_t GetOffset() const { return m_offset; }
- void SetOffset(dw_offset_t offset) { m_offset = offset; }
- DWARFDebugPubnamesSet::Header &GetHeader() { return m_header; }
- const DWARFDebugPubnamesSet::Header &GetHeader() const { return m_header; }
- const DWARFDebugPubnamesSet::Descriptor *GetDescriptor(uint32_t i) const {
- if (i < m_descriptors.size())
- return &m_descriptors[i];
- return NULL;
- }
- uint32_t NumDescriptors() const { return m_descriptors.size(); }
- void AddDescriptor(dw_offset_t cu_rel_offset, const char *name);
- void Clear();
- bool Extract(const lldb_private::DWARFDataExtractor &debug_pubnames_data,
- lldb::offset_t *offset_ptr);
- void Dump(lldb_private::Log *s) const;
- void InitNameIndexes() const;
- void Find(const char *name, bool ignore_case,
- std::vector<dw_offset_t> &die_offset_coll) const;
- void Find(const lldb_private::RegularExpression &regex,
- std::vector<dw_offset_t> &die_offsets) const;
- dw_offset_t GetOffsetOfNextEntry() const;
-
-protected:
- typedef std::vector<Descriptor> DescriptorColl;
- typedef DescriptorColl::iterator DescriptorIter;
- typedef DescriptorColl::const_iterator DescriptorConstIter;
-
- dw_offset_t m_offset;
- Header m_header;
-#if __cplusplus >= 201103L || defined(_MSC_VER)
- typedef std::unordered_multimap<const char *, uint32_t,
- std::hash<const char *>,
- CStringEqualBinaryPredicate>
- cstr_to_index_mmap;
-#else
- typedef __gnu_cxx::hash_multimap<const char *, uint32_t,
- __gnu_cxx::hash<const char *>,
- CStringEqualBinaryPredicate>
- cstr_to_index_mmap;
-#endif
- DescriptorColl m_descriptors;
- mutable cstr_to_index_mmap m_name_to_descriptor_index;
-};
-
-#endif // SymbolFileDWARF_DWARFDebugPubnamesSet_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index a8c48b7f2f84..89e27efb3cc2 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -89,8 +89,8 @@ void DWARFDebugRanges::Dump(Stream &s,
debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size)) {
dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
dw_addr_t end = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
- // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits
- // of ones
+ // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits of
+ // ones
if (begin == 0xFFFFFFFFull && addr_size == 4)
begin = LLDB_INVALID_ADDRESS;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
index 79f2f221696b..dbaf0b0ed127 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
@@ -67,8 +67,8 @@ bool DWARFDeclContext::operator==(const DWARFDeclContext &rhs) const {
// First compare the tags before we do expensive name compares
for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos) {
if (pos->tag != rhs_pos->tag) {
- // Check for DW_TAG_structure_type and DW_TAG_class_type as they are often
- // used interchangeably in GCC
+ // Check for DW_TAG_structure_type and DW_TAG_class_type as they are
+ // often used interchangeably in GCC
if (pos->tag == DW_TAG_structure_type &&
rhs_pos->tag == DW_TAG_class_type)
continue;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
index 2ff0fe3aac41..1d927ba3bca3 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
@@ -473,16 +473,6 @@ const char *DW_ORD_value_to_name(uint32_t val) {
return llvmstr.data();
}
-const char *DW_DSC_value_to_name(uint32_t val) {
- static char invalid[100];
- llvm::StringRef llvmstr = llvm::dwarf::DiscriminantString(val);
- if (llvmstr.empty()) {
- snprintf(invalid, sizeof(invalid), "Unknown DW_DSC constant: 0x%x", val);
- return invalid;
- }
- return llvmstr.data();
-}
-
const char *DW_LNS_value_to_name(uint32_t val) {
static char invalid[100];
llvm::StringRef llvmstr = llvm::dwarf::LNStandardString(val);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
index 038f5706c060..926f83b3564a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -58,8 +58,6 @@ const char *DW_INL_value_to_name(uint32_t val);
const char *DW_ORD_value_to_name(uint32_t val);
-const char *DW_DSC_value_to_name(uint32_t val);
-
const char *DW_LNS_value_to_name(uint32_t val);
const char *DW_LNE_value_to_name(uint32_t val);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index a21e313c2f81..4fde5748d3f3 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -12,10 +12,10 @@
#include "lldb/Core/dwarf.h"
#include "lldb/Utility/Stream.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFFormValue.h"
-class DWARFCompileUnit;
+class DWARFUnit;
using namespace lldb_private;
@@ -154,7 +154,7 @@ DWARFFormValue::GetFixedFormSizesForAddressSize(uint8_t addr_size,
DWARFFormValue::DWARFFormValue() : m_cu(NULL), m_form(0), m_value() {}
-DWARFFormValue::DWARFFormValue(const DWARFCompileUnit *cu, dw_form_t form)
+DWARFFormValue::DWARFFormValue(const DWARFUnit *cu, dw_form_t form)
: m_cu(cu), m_form(form), m_value() {}
void DWARFFormValue::Clear() {
@@ -177,7 +177,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
case DW_FORM_addr:
assert(m_cu);
m_value.value.uval = data.GetMaxU64(
- offset_ptr, DWARFCompileUnit::GetAddressByteSize(m_cu));
+ offset_ptr, DWARFUnit::GetAddressByteSize(m_cu));
break;
case DW_FORM_block2:
m_value.value.uval = data.GetU16(offset_ptr);
@@ -220,7 +220,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
case DW_FORM_strp:
assert(m_cu);
m_value.value.uval =
- data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);
+ data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4);
break;
// case DW_FORM_APPLE_db_str:
case DW_FORM_udata:
@@ -258,7 +258,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
case DW_FORM_sec_offset:
assert(m_cu);
m_value.value.uval =
- data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4);
+ data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4);
break;
case DW_FORM_flag_present:
m_value.value.uval = 1;
@@ -296,11 +296,11 @@ bool DWARFFormValue::SkipValue(const DWARFDataExtractor &debug_info_data,
bool DWARFFormValue::SkipValue(dw_form_t form,
const DWARFDataExtractor &debug_info_data,
lldb::offset_t *offset_ptr,
- const DWARFCompileUnit *cu) {
+ const DWARFUnit *cu) {
uint8_t ref_addr_size;
switch (form) {
- // Blocks if inlined data that have a length field and the data bytes
- // inlined in the .debug_info
+ // Blocks if inlined data that have a length field and the data bytes inlined
+ // in the .debug_info
case DW_FORM_exprloc:
case DW_FORM_block: {
dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr);
@@ -330,7 +330,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
// Compile unit address sized values
case DW_FORM_addr:
- *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
+ *offset_ptr += DWARFUnit::GetAddressByteSize(cu);
return true;
case DW_FORM_ref_addr:
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 2aa7460c4910..ef1a693b37c9 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -13,7 +13,7 @@
#include "DWARFDataExtractor.h"
#include <stddef.h> // for NULL
-class DWARFCompileUnit;
+class DWARFUnit;
class DWARFFormValue {
public:
@@ -55,9 +55,9 @@ public:
};
DWARFFormValue();
- DWARFFormValue(const DWARFCompileUnit *cu, dw_form_t form);
- const DWARFCompileUnit *GetCompileUnit() const { return m_cu; }
- void SetCompileUnit(const DWARFCompileUnit *cu) { m_cu = cu; }
+ DWARFFormValue(const DWARFUnit *cu, dw_form_t form);
+ const DWARFUnit *GetCompileUnit() const { return m_cu; }
+ void SetCompileUnit(const DWARFUnit *cu) { m_cu = cu; }
dw_form_t Form() const { return m_form; }
void SetForm(dw_form_t form) { m_form = form; }
const ValueType &Value() const { return m_value; }
@@ -79,7 +79,7 @@ public:
lldb::offset_t *offset_ptr) const;
static bool SkipValue(const dw_form_t form,
const lldb_private::DWARFDataExtractor &debug_info_data,
- lldb::offset_t *offset_ptr, const DWARFCompileUnit *cu);
+ lldb::offset_t *offset_ptr, const DWARFUnit *cu);
static bool IsBlockForm(const dw_form_t form);
static bool IsDataForm(const dw_form_t form);
static FixedFormSizes GetFixedFormSizesForAddressSize(uint8_t addr_size,
@@ -89,7 +89,7 @@ public:
static bool FormIsSupported(dw_form_t form);
protected:
- const DWARFCompileUnit *m_cu; // Compile unit for this form
+ const DWARFUnit *m_cu; // Compile unit for this form
dw_form_t m_form; // Form for this value
ValueType m_value; // Contains all data for the form
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
new file mode 100644
index 000000000000..4577f0557a1d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
@@ -0,0 +1,68 @@
+//===-- DWARFIndex.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+DWARFIndex::~DWARFIndex() = default;
+
+void DWARFIndex::ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
+ DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+ DWARFDIE die = info.GetDIE(ref);
+ if (!die) {
+ ReportInvalidDIEOffset(ref.die_offset, name);
+ return;
+ }
+
+ // Exit early if we're searching exclusively for methods or selectors and
+ // we have a context specified (no methods in namespaces).
+ uint32_t looking_for_nonmethods =
+ name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector);
+ if (!looking_for_nonmethods && parent_decl_ctx.IsValid())
+ return;
+
+ // Otherwise, we need to also check that the context matches. If it does not
+ // match, we do nothing.
+ if (!SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
+ return;
+
+ // In case of a full match, we just insert everything we find.
+ if (name_type_mask & eFunctionNameTypeFull) {
+ dies.push_back(die);
+ return;
+ }
+
+ // If looking for ObjC selectors, we need to also check if the name is a
+ // possible selector.
+ if (name_type_mask & eFunctionNameTypeSelector &&
+ ObjCLanguage::IsPossibleObjCMethodName(die.GetName())) {
+ dies.push_back(die);
+ return;
+ }
+
+ bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod;
+ bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase;
+ if (looking_for_methods || looking_for_functions) {
+ // If we're looking for either methods or functions, we definitely want this
+ // die. Otherwise, only keep it if the die type matches what we are
+ // searching for.
+ if ((looking_for_methods && looking_for_functions) ||
+ looking_for_methods == die.IsMethod())
+ dies.push_back(die);
+ }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
new file mode 100644
index 000000000000..77af67b8e60f
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
@@ -0,0 +1,69 @@
+//===-- DWARFIndex.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_DWARFINDEX_H
+#define LLDB_DWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DIERef.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/SymbolFile/DWARF/DWARFFormValue.h"
+
+class DWARFDebugInfo;
+class DWARFDeclContext;
+class DWARFDIE;
+
+namespace lldb_private {
+class DWARFIndex {
+public:
+ DWARFIndex(Module &module) : m_module(module) {}
+ virtual ~DWARFIndex();
+
+ virtual void Preload() = 0;
+
+ /// Finds global variables with the given base name. Any additional filtering
+ /// (e.g., to only retrieve variables from a given context) should be done by
+ /// the consumer.
+ virtual void GetGlobalVariables(ConstString basename, DIEArray &offsets) = 0;
+
+ virtual void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) = 0;
+ virtual void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) = 0;
+ virtual void GetObjCMethods(ConstString class_name, DIEArray &offsets) = 0;
+ virtual void GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) = 0;
+ virtual void GetTypes(ConstString name, DIEArray &offsets) = 0;
+ virtual void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) = 0;
+ virtual void GetNamespaces(ConstString name, DIEArray &offsets) = 0;
+ virtual void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) = 0;
+ virtual void GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) = 0;
+
+ virtual void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) = 0;
+ virtual void Dump(Stream &s) = 0;
+
+protected:
+ Module &m_module;
+
+ /// Helper function implementing common logic for processing function dies. If
+ /// the function given by "ref" matches search criteria given by
+ /// "parent_decl_ctx" and "name_type_mask", it is inserted into the "dies"
+ /// vector.
+ void ProcessFunctionDIE(llvm::StringRef name, DIERef ref,
+ DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask, std::vector<DWARFDIE> &dies);
+};
+} // namespace lldb_private
+
+#endif // LLDB_DWARFINDEX_H
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
new file mode 100644
index 000000000000..f44b2bb97b2b
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -0,0 +1,755 @@
+//===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFUnit.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Host/StringConvert.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/Timer.h"
+
+#include "DWARFDIECollection.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "SymbolFileDWARFDwo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+extern int g_verbose;
+
+DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf)
+ : m_dwarf(dwarf), m_cancel_scopes(false) {}
+
+DWARFUnit::~DWARFUnit() {}
+
+//----------------------------------------------------------------------
+// Parses first DIE of a compile unit.
+//----------------------------------------------------------------------
+void DWARFUnit::ExtractUnitDIEIfNeeded() {
+ {
+ llvm::sys::ScopedReader lock(m_first_die_mutex);
+ if (m_first_die)
+ return; // Already parsed
+ }
+ llvm::sys::ScopedWriter lock(m_first_die_mutex);
+ if (m_first_die)
+ return; // Already parsed
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(
+ func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset);
+
+ // Set the offset to that of the first DIE and calculate the start of the
+ // next compilation unit header.
+ lldb::offset_t offset = GetFirstDIEOffset();
+
+ // We are in our compile unit, parse starting at the offset we were told to
+ // parse
+ const DWARFDataExtractor &data = GetData();
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
+ IsDWARF64());
+ if (offset < GetNextCompileUnitOffset() &&
+ m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) {
+ AddUnitDIE(m_first_die);
+ return;
+ }
+
+ ExtractDIEsEndCheck(offset);
+}
+
+//----------------------------------------------------------------------
+// Parses a compile unit and indexes its DIEs if it hasn't already been done.
+// It will leave this compile unit extracted forever.
+//----------------------------------------------------------------------
+void DWARFUnit::ExtractDIEsIfNeeded() {
+ m_cancel_scopes = true;
+
+ {
+ llvm::sys::ScopedReader lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return; // Already parsed
+ }
+ llvm::sys::ScopedWriter lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return; // Already parsed
+
+ ExtractDIEsRWLocked();
+}
+
+//----------------------------------------------------------------------
+// Parses a compile unit and indexes its DIEs if it hasn't already been done.
+// It will clear this compile unit after returned instance gets out of scope,
+// no other ScopedExtractDIEs instance is running for this compile unit
+// and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs
+// lifetime.
+//----------------------------------------------------------------------
+DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() {
+ ScopedExtractDIEs scoped(this);
+
+ {
+ llvm::sys::ScopedReader lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return scoped; // Already parsed
+ }
+ llvm::sys::ScopedWriter lock(m_die_array_mutex);
+ if (!m_die_array.empty())
+ return scoped; // Already parsed
+
+ // Otherwise m_die_array would be already populated.
+ lldbassert(!m_cancel_scopes);
+
+ ExtractDIEsRWLocked();
+ scoped.m_clear_dies = true;
+ return scoped;
+}
+
+DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit *cu) : m_cu(cu) {
+ lldbassert(m_cu);
+ m_cu->m_die_array_scoped_mutex.lock_shared();
+}
+
+DWARFUnit::ScopedExtractDIEs::~ScopedExtractDIEs() {
+ if (!m_cu)
+ return;
+ m_cu->m_die_array_scoped_mutex.unlock_shared();
+ if (!m_clear_dies || m_cu->m_cancel_scopes)
+ return;
+ // Be sure no other ScopedExtractDIEs is running anymore.
+ llvm::sys::ScopedWriter lock_scoped(m_cu->m_die_array_scoped_mutex);
+ llvm::sys::ScopedWriter lock(m_cu->m_die_array_mutex);
+ if (m_cu->m_cancel_scopes)
+ return;
+ m_cu->ClearDIEsRWLocked();
+}
+
+DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs)
+ : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) {
+ rhs.m_cu = nullptr;
+}
+
+DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=(
+ DWARFUnit::ScopedExtractDIEs &&rhs) {
+ m_cu = rhs.m_cu;
+ rhs.m_cu = nullptr;
+ m_clear_dies = rhs.m_clear_dies;
+ return *this;
+}
+
+//----------------------------------------------------------------------
+// Parses a compile unit and indexes its DIEs, m_die_array_mutex must be
+// held R/W and m_die_array must be empty.
+//----------------------------------------------------------------------
+void DWARFUnit::ExtractDIEsRWLocked() {
+ llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex);
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(
+ func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset);
+
+ // Set the offset to that of the first DIE and calculate the start of the
+ // next compilation unit header.
+ lldb::offset_t offset = GetFirstDIEOffset();
+ lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
+
+ DWARFDebugInfoEntry die;
+ // Keep a flat array of the DIE for binary lookup by DIE offset
+ Log *log(
+ LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
+ if (log) {
+ m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+ log,
+ "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at "
+ ".debug_info[0x%8.8x]",
+ GetOffset());
+ }
+
+ uint32_t depth = 0;
+ // We are in our compile unit, parse starting at the offset we were told to
+ // parse
+ const DWARFDataExtractor &data = GetData();
+ std::vector<uint32_t> die_index_stack;
+ die_index_stack.reserve(32);
+ die_index_stack.push_back(0);
+ bool prev_die_had_children = false;
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
+ IsDWARF64());
+ while (offset < next_cu_offset &&
+ die.FastExtract(data, this, fixed_form_sizes, &offset)) {
+ // if (log)
+ // log->Printf("0x%8.8x: %*.*s%s%s",
+ // die.GetOffset(),
+ // depth * 2, depth * 2, "",
+ // DW_TAG_value_to_name (die.Tag()),
+ // die.HasChildren() ? " *" : "");
+
+ const bool null_die = die.IsNULL();
+ if (depth == 0) {
+ assert(m_die_array.empty() && "Compile unit DIE already added");
+
+ // The average bytes per DIE entry has been seen to be around 14-20 so
+ // lets pre-reserve half of that since we are now stripping the NULL
+ // tags.
+
+ // Only reserve the memory if we are adding children of the main
+ // compile unit DIE. The compile unit DIE is always the first entry, so
+ // if our size is 1, then we are adding the first compile unit child
+ // DIE and should reserve the memory.
+ m_die_array.reserve(GetDebugInfoSize() / 24);
+ m_die_array.push_back(die);
+
+ if (!m_first_die)
+ AddUnitDIE(m_die_array.front());
+ } else {
+ if (null_die) {
+ if (prev_die_had_children) {
+ // This will only happen if a DIE says is has children but all it
+ // contains is a NULL tag. Since we are removing the NULL DIEs from
+ // the list (saves up to 25% in C++ code), we need a way to let the
+ // DIE know that it actually doesn't have children.
+ if (!m_die_array.empty())
+ m_die_array.back().SetEmptyChildren(true);
+ }
+ } else {
+ die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]);
+
+ if (die_index_stack.back())
+ m_die_array[die_index_stack.back()].SetSiblingIndex(
+ m_die_array.size() - die_index_stack.back());
+
+ // Only push the DIE if it isn't a NULL DIE
+ m_die_array.push_back(die);
+ }
+ }
+
+ if (null_die) {
+ // NULL DIE.
+ if (!die_index_stack.empty())
+ die_index_stack.pop_back();
+
+ if (depth > 0)
+ --depth;
+ if (depth == 0)
+ break; // We are done with this compile unit!
+
+ prev_die_had_children = false;
+ } else {
+ die_index_stack.back() = m_die_array.size() - 1;
+ // Normal DIE
+ const bool die_has_children = die.HasChildren();
+ if (die_has_children) {
+ die_index_stack.push_back(0);
+ ++depth;
+ }
+ prev_die_had_children = die_has_children;
+ }
+ }
+
+ if (!m_die_array.empty()) {
+ lldbassert(!m_first_die || m_first_die == m_die_array.front());
+ m_first_die = m_die_array.front();
+ }
+
+ m_die_array.shrink_to_fit();
+
+ ExtractDIEsEndCheck(offset);
+
+ if (m_dwo_symbol_file) {
+ DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ dwo_cu->ExtractDIEsIfNeeded();
+ }
+}
+
+//--------------------------------------------------------------------------
+// Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded().
+//--------------------------------------------------------------------------
+void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const {
+ // Give a little bit of info if we encounter corrupt DWARF (our offset should
+ // always terminate at or before the start of the next compilation unit
+ // header).
+ if (offset > GetNextCompileUnitOffset()) {
+ m_dwarf->GetObjectFile()->GetModule()->ReportWarning(
+ "DWARF compile unit extends beyond its bounds cu 0x%8.8x at "
+ "0x%8.8" PRIx64 "\n",
+ GetOffset(), offset);
+ }
+
+ Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+ if (log && log->GetVerbose()) {
+ StreamString strm;
+ Dump(&strm);
+ if (m_die_array.empty())
+ strm.Printf("error: no DIE for compile unit");
+ else
+ m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX);
+ log->PutString(strm.GetString());
+ }
+}
+
+// m_die_array_mutex must be already held as read/write.
+void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
+ uint64_t base_addr = cu_die.GetAttributeValueAsAddress(
+ m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ if (base_addr == LLDB_INVALID_ADDRESS)
+ base_addr = cu_die.GetAttributeValueAsAddress(
+ m_dwarf, this, DW_AT_entry_pc, 0);
+ SetBaseAddress(base_addr);
+
+ std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
+ m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die);
+ if (!dwo_symbol_file)
+ return;
+
+ DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
+ if (!dwo_cu)
+ return; // Can't fetch the compile unit from the dwo file.
+
+ DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
+ if (!dwo_cu_die.IsValid())
+ return; // Can't fetch the compile unit DIE from the dwo file.
+
+ uint64_t main_dwo_id =
+ cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0);
+ uint64_t sub_dwo_id =
+ dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0);
+ if (main_dwo_id != sub_dwo_id)
+ return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to
+ // a differectn compilation.
+
+ m_dwo_symbol_file = std::move(dwo_symbol_file);
+
+ dw_addr_t addr_base =
+ cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0);
+ dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
+ m_dwarf, this, DW_AT_GNU_ranges_base, 0);
+ dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset);
+}
+
+DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
+ if (DIE()) {
+ const DWARFDebugAranges &func_aranges = GetFunctionAranges();
+
+ // Re-check the aranges auto pointer contents in case it was created above
+ if (!func_aranges.IsEmpty())
+ return GetDIE(func_aranges.FindAddress(address));
+ }
+ return DWARFDIE();
+}
+
+size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
+ DWARFDIECollection &dies,
+ uint32_t depth) const {
+ size_t old_size = dies.Size();
+ {
+ llvm::sys::ScopedReader lock(m_die_array_mutex);
+ DWARFDebugInfoEntry::const_iterator pos;
+ DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+ for (pos = m_die_array.begin(); pos != end; ++pos) {
+ if (pos->Tag() == tag)
+ dies.Append(DWARFDIE(this, &(*pos)));
+ }
+ }
+
+ // Return the number of DIEs added to the collection
+ return dies.Size() - old_size;
+}
+
+
+lldb::user_id_t DWARFUnit::GetID() const {
+ dw_offset_t local_id =
+ m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
+ if (m_dwarf)
+ return DIERef(local_id, local_id).GetUID(m_dwarf);
+ else
+ return local_id;
+}
+
+dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const {
+ return m_offset + GetLengthByteSize() + GetLength();
+}
+
+size_t DWARFUnit::GetDebugInfoSize() const {
+ return GetLengthByteSize() + GetLength() - GetHeaderByteSize();
+}
+
+const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const {
+ return m_abbrevs;
+}
+
+dw_offset_t DWARFUnit::GetAbbrevOffset() const {
+ return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
+}
+
+void DWARFUnit::SetAddrBase(dw_addr_t addr_base,
+ dw_addr_t ranges_base,
+ dw_offset_t base_obj_offset) {
+ m_addr_base = addr_base;
+ m_ranges_base = ranges_base;
+ m_base_obj_offset = base_obj_offset;
+}
+
+// It may be called only with m_die_array_mutex held R/W.
+void DWARFUnit::ClearDIEsRWLocked() {
+ m_die_array.clear();
+ m_die_array.shrink_to_fit();
+
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked();
+}
+
+void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf,
+ DWARFDebugAranges *debug_aranges) {
+ // This function is usually called if there in no .debug_aranges section in
+ // order to produce a compile unit level set of address ranges that is
+ // accurate.
+
+ size_t num_debug_aranges = debug_aranges->GetNumRanges();
+
+ // First get the compile unit DIE only and check if it has a DW_AT_ranges
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+
+ const dw_offset_t cu_offset = GetOffset();
+ if (die) {
+ DWARFRangeList ranges;
+ const size_t num_ranges =
+ die->GetAttributeAddressRanges(dwarf, this, ranges, false);
+ if (num_ranges > 0) {
+ // This compile unit has DW_AT_ranges, assume this is correct if it is
+ // present since clang no longer makes .debug_aranges by default and it
+ // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with
+ // recent GCC builds.
+ for (size_t i = 0; i < num_ranges; ++i) {
+ const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
+ debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
+ range.GetRangeEnd());
+ }
+
+ return; // We got all of our ranges from the DW_AT_ranges attribute
+ }
+ }
+ // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF
+
+ // If the DIEs weren't parsed, then we don't want all dies for all compile
+ // units to stay loaded when they weren't needed. So we can end up parsing
+ // the DWARF and then throwing them all away to keep memory usage down.
+ ScopedExtractDIEs clear_dies(ExtractDIEsScoped());
+
+ die = DIEPtr();
+ if (die)
+ die->BuildAddressRangeTable(dwarf, this, debug_aranges);
+
+ if (debug_aranges->GetNumRanges() == num_debug_aranges) {
+ // We got nothing from the functions, maybe we have a line tables only
+ // situation. Check the line tables and build the arange table from this.
+ SymbolContext sc;
+ sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this);
+ if (sc.comp_unit) {
+ SymbolFileDWARFDebugMap *debug_map_sym_file =
+ m_dwarf->GetDebugMapSymfile();
+ if (debug_map_sym_file == NULL) {
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table) {
+ LineTable::FileAddressRanges file_ranges;
+ const bool append = true;
+ const size_t num_ranges =
+ line_table->GetContiguousFileAddressRanges(file_ranges, append);
+ for (uint32_t idx = 0; idx < num_ranges; ++idx) {
+ const LineTable::FileAddressRanges::Entry &range =
+ file_ranges.GetEntryRef(idx);
+ debug_aranges->AppendRange(cu_offset, range.GetRangeBase(),
+ range.GetRangeEnd());
+ }
+ }
+ } else
+ debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges);
+ }
+ }
+
+ if (debug_aranges->GetNumRanges() == num_debug_aranges) {
+ // We got nothing from the functions, maybe we have a line tables only
+ // situation. Check the line tables and build the arange table from this.
+ SymbolContext sc;
+ sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this);
+ if (sc.comp_unit) {
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table) {
+ LineTable::FileAddressRanges file_ranges;
+ const bool append = true;
+ const size_t num_ranges =
+ line_table->GetContiguousFileAddressRanges(file_ranges, append);
+ for (uint32_t idx = 0; idx < num_ranges; ++idx) {
+ const LineTable::FileAddressRanges::Entry &range =
+ file_ranges.GetEntryRef(idx);
+ debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(),
+ range.GetRangeEnd());
+ }
+ }
+ }
+ }
+}
+
+lldb::ByteOrder DWARFUnit::GetByteOrder() const {
+ return m_dwarf->GetObjectFile()->GetByteOrder();
+}
+
+TypeSystem *DWARFUnit::GetTypeSystem() {
+ if (m_dwarf)
+ return m_dwarf->GetTypeSystemForLanguage(GetLanguageType());
+ else
+ return nullptr;
+}
+
+DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() {
+ return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
+ IsDWARF64());
+}
+
+void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
+
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
+ const dw_offset_t die_offset) {
+ return die.GetOffset() < die_offset;
+}
+
+//----------------------------------------------------------------------
+// GetDIE()
+//
+// Get the DIE (Debug Information Entry) with the specified offset by first
+// checking if the DIE is contained within this compile unit and grabbing the
+// DIE from this compile unit. Otherwise we grab the DIE from the DWARF file.
+//----------------------------------------------------------------------
+DWARFDIE
+DWARFUnit::GetDIE(dw_offset_t die_offset) {
+ if (die_offset != DW_INVALID_OFFSET) {
+ if (GetDwoSymbolFile())
+ return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset);
+
+ if (ContainsDIEOffset(die_offset)) {
+ ExtractDIEsIfNeeded();
+ DWARFDebugInfoEntry::const_iterator end = m_die_array.cend();
+ DWARFDebugInfoEntry::const_iterator pos =
+ lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset);
+ if (pos != end) {
+ if (die_offset == (*pos).GetOffset())
+ return DWARFDIE(this, &(*pos));
+ }
+ } else {
+ // Don't specify the compile unit offset as we don't know it because the
+ // DIE belongs to
+ // a different compile unit in the same symbol file.
+ return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset);
+ }
+ }
+ return DWARFDIE(); // Not found
+}
+
+uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) {
+ if (cu)
+ return cu->GetAddressByteSize();
+ return DWARFUnit::GetDefaultAddressSize();
+}
+
+bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) {
+ if (cu)
+ return cu->IsDWARF64();
+ return false;
+}
+
+uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; }
+
+void *DWARFUnit::GetUserData() const { return m_user_data; }
+
+void DWARFUnit::SetUserData(void *d) {
+ m_user_data = d;
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->SetUserData(d);
+}
+
+bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() {
+ if (GetProducer() == eProducerLLVMGCC)
+ return false;
+ return true;
+}
+
+bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() {
+ // llvm-gcc makes completely invalid decl file attributes and won't ever be
+ // fixed, so we need to know to ignore these.
+ return GetProducer() == eProducerLLVMGCC;
+}
+
+bool DWARFUnit::Supports_unnamed_objc_bitfields() {
+ if (GetProducer() == eProducerClang) {
+ const uint32_t major_version = GetProducerVersionMajor();
+ if (major_version > 425 ||
+ (major_version == 425 && GetProducerVersionUpdate() >= 13))
+ return true;
+ else
+ return false;
+ }
+ return true; // Assume all other compilers didn't have incorrect ObjC bitfield
+ // info
+}
+
+SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; }
+
+void DWARFUnit::ParseProducerInfo() {
+ m_producer_version_major = UINT32_MAX;
+ m_producer_version_minor = UINT32_MAX;
+ m_producer_version_update = UINT32_MAX;
+
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+ if (die) {
+
+ const char *producer_cstr =
+ die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL);
+ if (producer_cstr) {
+ RegularExpression llvm_gcc_regex(
+ llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple "
+ "Inc\\. build [0-9]+\\) \\(LLVM build "
+ "[\\.0-9]+\\)$"));
+ if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) {
+ m_producer = eProducerLLVMGCC;
+ } else if (strstr(producer_cstr, "clang")) {
+ static RegularExpression g_clang_version_regex(
+ llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)"));
+ RegularExpression::Match regex_match(3);
+ if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr),
+ &regex_match)) {
+ std::string str;
+ if (regex_match.GetMatchAtIndex(producer_cstr, 1, str))
+ m_producer_version_major =
+ StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
+ if (regex_match.GetMatchAtIndex(producer_cstr, 2, str))
+ m_producer_version_minor =
+ StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
+ if (regex_match.GetMatchAtIndex(producer_cstr, 3, str))
+ m_producer_version_update =
+ StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10);
+ }
+ m_producer = eProducerClang;
+ } else if (strstr(producer_cstr, "GNU"))
+ m_producer = eProducerGCC;
+ }
+ }
+ if (m_producer == eProducerInvalid)
+ m_producer = eProcucerOther;
+}
+
+DWARFProducer DWARFUnit::GetProducer() {
+ if (m_producer == eProducerInvalid)
+ ParseProducerInfo();
+ return m_producer;
+}
+
+uint32_t DWARFUnit::GetProducerVersionMajor() {
+ if (m_producer_version_major == 0)
+ ParseProducerInfo();
+ return m_producer_version_major;
+}
+
+uint32_t DWARFUnit::GetProducerVersionMinor() {
+ if (m_producer_version_minor == 0)
+ ParseProducerInfo();
+ return m_producer_version_minor;
+}
+
+uint32_t DWARFUnit::GetProducerVersionUpdate() {
+ if (m_producer_version_update == 0)
+ ParseProducerInfo();
+ return m_producer_version_update;
+}
+LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) {
+ // Note: user languages between lo_user and hi_user must be handled
+ // explicitly here.
+ switch (val) {
+ case DW_LANG_Mips_Assembler:
+ return eLanguageTypeMipsAssembler;
+ case DW_LANG_GOOGLE_RenderScript:
+ return eLanguageTypeExtRenderScript;
+ default:
+ return static_cast<LanguageType>(val);
+ }
+}
+
+LanguageType DWARFUnit::GetLanguageType() {
+ if (m_language_type != eLanguageTypeUnknown)
+ return m_language_type;
+
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+ if (die)
+ m_language_type = LanguageTypeFromDWARF(
+ die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0));
+ return m_language_type;
+}
+
+bool DWARFUnit::GetIsOptimized() {
+ if (m_is_optimized == eLazyBoolCalculate) {
+ const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+ if (die) {
+ m_is_optimized = eLazyBoolNo;
+ if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized,
+ 0) == 1) {
+ m_is_optimized = eLazyBoolYes;
+ }
+ }
+ }
+ return m_is_optimized == eLazyBoolYes;
+}
+
+SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
+ return m_dwo_symbol_file.get();
+}
+
+dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; }
+
+const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() {
+ if (m_func_aranges_ap.get() == NULL) {
+ m_func_aranges_ap.reset(new DWARFDebugAranges());
+ Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
+
+ if (log) {
+ m_dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "DWARFUnit::GetFunctionAranges() for compile unit at "
+ ".debug_info[0x%8.8x]",
+ GetOffset());
+ }
+ const DWARFDebugInfoEntry *die = DIEPtr();
+ if (die)
+ die->BuildFunctionAddressRangeTable(m_dwarf, this,
+ m_func_aranges_ap.get());
+
+ if (m_dwo_symbol_file) {
+ DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr();
+ if (dwo_die)
+ dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu,
+ m_func_aranges_ap.get());
+ }
+
+ const bool minimize = false;
+ m_func_aranges_ap->Sort(minimize);
+ }
+ return *m_func_aranges_ap.get();
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
new file mode 100644
index 000000000000..c9e48c538bc1
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -0,0 +1,252 @@
+//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFUnit_h_
+#define SymbolFileDWARF_DWARFUnit_h_
+
+#include "DWARFDIE.h"
+#include "DWARFDebugInfoEntry.h"
+#include "lldb/lldb-enumerations.h"
+#include "llvm/Support/RWMutex.h"
+#include <atomic>
+
+class DWARFUnit;
+class DWARFCompileUnit;
+class NameToDIE;
+class SymbolFileDWARF;
+class SymbolFileDWARFDwo;
+
+typedef std::shared_ptr<DWARFUnit> DWARFUnitSP;
+
+enum DWARFProducer {
+ eProducerInvalid = 0,
+ eProducerClang,
+ eProducerGCC,
+ eProducerLLVMGCC,
+ eProcucerOther
+};
+
+class DWARFUnit {
+ friend class DWARFCompileUnit;
+
+ using die_iterator_range =
+ llvm::iterator_range<DWARFDebugInfoEntry::collection::iterator>;
+
+public:
+ virtual ~DWARFUnit();
+
+ void ExtractUnitDIEIfNeeded();
+ void ExtractDIEsIfNeeded();
+
+ class ScopedExtractDIEs {
+ DWARFUnit *m_cu;
+ public:
+ bool m_clear_dies = false;
+ ScopedExtractDIEs(DWARFUnit *cu);
+ ~ScopedExtractDIEs();
+ DISALLOW_COPY_AND_ASSIGN(ScopedExtractDIEs);
+ ScopedExtractDIEs(ScopedExtractDIEs &&rhs);
+ ScopedExtractDIEs &operator=(ScopedExtractDIEs &&rhs);
+ };
+ ScopedExtractDIEs ExtractDIEsScoped();
+
+ DWARFDIE LookupAddress(const dw_addr_t address);
+ size_t AppendDIEsWithTag(const dw_tag_t tag,
+ DWARFDIECollection &matching_dies,
+ uint32_t depth = UINT32_MAX) const;
+ bool Verify(lldb_private::Stream *s) const;
+ virtual void Dump(lldb_private::Stream *s) const = 0;
+ //------------------------------------------------------------------
+ /// Get the data that contains the DIE information for this unit.
+ ///
+ /// This will return the correct bytes that contain the data for
+ /// this DWARFUnit. It could be .debug_info or .debug_types
+ /// depending on where the data for this unit originates.
+ ///
+ /// @return
+ /// The correct data for the DIE information in this unit.
+ //------------------------------------------------------------------
+ virtual const lldb_private::DWARFDataExtractor &GetData() const = 0;
+ //------------------------------------------------------------------
+ /// Get the size in bytes of the compile unit header.
+ ///
+ /// @return
+ /// Byte size of the compile unit header
+ //------------------------------------------------------------------
+ virtual uint32_t GetHeaderByteSize() const = 0;
+ // Offset of the initial length field.
+ dw_offset_t GetOffset() const { return m_offset; }
+ lldb::user_id_t GetID() const;
+ //------------------------------------------------------------------
+ /// Get the size in bytes of the length field in the header.
+ ///
+ /// In DWARF32 this is just 4 bytes, and DWARF64 it is 12 where 4
+ /// are 0xFFFFFFFF followed by the actual 64 bit length.
+ ///
+ /// @return
+ /// Byte size of the compile unit header length field
+ //------------------------------------------------------------------
+ size_t GetLengthByteSize() const { return IsDWARF64() ? 12 : 4; }
+
+ bool ContainsDIEOffset(dw_offset_t die_offset) const {
+ return die_offset >= GetFirstDIEOffset() &&
+ die_offset < GetNextCompileUnitOffset();
+ }
+ dw_offset_t GetFirstDIEOffset() const {
+ return m_offset + GetHeaderByteSize();
+ }
+ dw_offset_t GetNextCompileUnitOffset() const;
+ // Size of the CU data (without initial length and without header).
+ size_t GetDebugInfoSize() const;
+ // Size of the CU data incl. header but without initial length.
+ uint32_t GetLength() const { return m_length; }
+ uint16_t GetVersion() const { return m_version; }
+ const DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
+ dw_offset_t GetAbbrevOffset() const;
+ uint8_t GetAddressByteSize() const { return m_addr_size; }
+ dw_addr_t GetBaseAddress() const { return m_base_addr; }
+ dw_addr_t GetAddrBase() const { return m_addr_base; }
+ dw_addr_t GetRangesBase() const { return m_ranges_base; }
+ void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base,
+ dw_offset_t base_obj_offset);
+ void BuildAddressRangeTable(SymbolFileDWARF *dwarf,
+ DWARFDebugAranges *debug_aranges);
+
+ lldb::ByteOrder GetByteOrder() const;
+
+ lldb_private::TypeSystem *GetTypeSystem();
+
+ const DWARFDebugAranges &GetFunctionAranges();
+
+ DWARFFormValue::FixedFormSizes GetFixedFormSizes();
+
+ void SetBaseAddress(dw_addr_t base_addr);
+
+ DWARFBaseDIE GetUnitDIEOnly() { return DWARFDIE(this, GetUnitDIEPtrOnly()); }
+
+ DWARFDIE DIE() { return DWARFDIE(this, DIEPtr()); }
+
+ DWARFDIE GetDIE(dw_offset_t die_offset);
+
+ static uint8_t GetAddressByteSize(const DWARFUnit *cu);
+
+ static bool IsDWARF64(const DWARFUnit *cu);
+
+ static uint8_t GetDefaultAddressSize();
+
+ void *GetUserData() const;
+
+ void SetUserData(void *d);
+
+ bool Supports_DW_AT_APPLE_objc_complete_type();
+
+ bool DW_AT_decl_file_attributes_are_invalid();
+
+ bool Supports_unnamed_objc_bitfields();
+
+ SymbolFileDWARF *GetSymbolFileDWARF() const;
+
+ DWARFProducer GetProducer();
+
+ uint32_t GetProducerVersionMajor();
+
+ uint32_t GetProducerVersionMinor();
+
+ uint32_t GetProducerVersionUpdate();
+
+ static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
+
+ lldb::LanguageType GetLanguageType();
+
+ bool IsDWARF64() const { return m_is_dwarf64; }
+
+ bool GetIsOptimized();
+
+ SymbolFileDWARFDwo *GetDwoSymbolFile() const;
+
+ dw_offset_t GetBaseObjOffset() const;
+
+ die_iterator_range dies() {
+ ExtractDIEsIfNeeded();
+ return die_iterator_range(m_die_array.begin(), m_die_array.end());
+ }
+
+protected:
+ DWARFUnit(SymbolFileDWARF *dwarf);
+
+ SymbolFileDWARF *m_dwarf = nullptr;
+ std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
+ const DWARFAbbreviationDeclarationSet *m_abbrevs = nullptr;
+ void *m_user_data = nullptr;
+ // The compile unit debug information entry item
+ DWARFDebugInfoEntry::collection m_die_array;
+ mutable llvm::sys::RWMutex m_die_array_mutex;
+ // It is used for tracking of ScopedExtractDIEs instances.
+ mutable llvm::sys::RWMutex m_die_array_scoped_mutex;
+ // ScopedExtractDIEs instances should not call ClearDIEsRWLocked()
+ // as someone called ExtractDIEsIfNeeded().
+ std::atomic<bool> m_cancel_scopes;
+ // GetUnitDIEPtrOnly() needs to return pointer to the first DIE.
+ // But the first element of m_die_array after ExtractUnitDIEIfNeeded()
+ // would possibly move in memory after later ExtractDIEsIfNeeded().
+ DWARFDebugInfoEntry m_first_die;
+ llvm::sys::RWMutex m_first_die_mutex;
+ // A table similar to the .debug_aranges table, but this one points to the
+ // exact DW_TAG_subprogram DIEs
+ std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap;
+ dw_addr_t m_base_addr = 0;
+ dw_offset_t m_length = 0;
+ uint16_t m_version = 0;
+ uint8_t m_addr_size = 0;
+ DWARFProducer m_producer = eProducerInvalid;
+ uint32_t m_producer_version_major = 0;
+ uint32_t m_producer_version_minor = 0;
+ uint32_t m_producer_version_update = 0;
+ lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown;
+ bool m_is_dwarf64 = false;
+ lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
+ dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
+ dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
+ // If this is a dwo compile unit this is the offset of the base compile unit
+ // in the main object file
+ dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;
+
+ // Offset of the initial length field.
+ dw_offset_t m_offset;
+
+private:
+ void ParseProducerInfo();
+ void ExtractDIEsRWLocked();
+ void ClearDIEsRWLocked();
+
+ // Get the DWARF unit DWARF debug informration entry. Parse the single DIE
+ // if needed.
+ const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
+ ExtractUnitDIEIfNeeded();
+ // m_first_die_mutex is not required as m_first_die is never cleared.
+ if (!m_first_die)
+ return NULL;
+ return &m_first_die;
+ }
+
+ // Get all DWARF debug informration entries. Parse all DIEs if needed.
+ const DWARFDebugInfoEntry *DIEPtr() {
+ ExtractDIEsIfNeeded();
+ if (m_die_array.empty())
+ return NULL;
+ return &m_die_array[0];
+ }
+
+ void AddUnitDIE(const DWARFDebugInfoEntry &cu_die);
+ void ExtractDIEsEndCheck(lldb::offset_t offset) const;
+
+ DISALLOW_COPY_AND_ASSIGN(DWARFUnit);
+};
+
+#endif // SymbolFileDWARF_DWARFUnit_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
new file mode 100644
index 000000000000..614ff470d161
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -0,0 +1,272 @@
+//===-- DebugNamesDWARFIndex.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
+#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Stream.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data) {
+ return llvm::DWARFDataExtractor(
+ llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
+ data.GetByteSize()),
+ data.GetByteOrder() == eByteOrderLittle, data.GetAddressByteSize());
+}
+
+llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
+DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
+ DWARFDataExtractor debug_str,
+ DWARFDebugInfo *debug_info) {
+ if (!debug_info) {
+ return llvm::make_error<llvm::StringError>("debug info null",
+ llvm::inconvertibleErrorCode());
+ }
+ auto index_up =
+ llvm::make_unique<DebugNames>(ToLLVM(debug_names), ToLLVM(debug_str));
+ if (llvm::Error E = index_up->extract())
+ return std::move(E);
+
+ return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
+ module, std::move(index_up), debug_names, debug_str, *debug_info));
+}
+
+llvm::DenseSet<dw_offset_t>
+DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
+ llvm::DenseSet<dw_offset_t> result;
+ for (const DebugNames::NameIndex &ni : debug_names) {
+ for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
+ result.insert(ni.getCUOffset(cu));
+ }
+ return result;
+}
+
+DIERef DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) {
+ llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
+ if (!cu_offset)
+ return DIERef();
+
+ DWARFUnit *cu = m_debug_info.GetCompileUnit(*cu_offset);
+ if (!cu)
+ return DIERef();
+
+ // This initializes the DWO symbol file. It's not possible for
+ // GetDwoSymbolFile to call this automatically because of mutual recursion
+ // between this and DWARFDebugInfoEntry::GetAttributeValue.
+ cu->ExtractUnitDIEIfNeeded();
+ uint64_t die_bias = cu->GetDwoSymbolFile() ? 0 : *cu_offset;
+
+ if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
+ return DIERef(*cu_offset, die_bias + *die_offset);
+
+ return DIERef();
+}
+
+void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry,
+ DIEArray &offsets) {
+ if (DIERef ref = ToDIERef(entry))
+ offsets.push_back(ref);
+}
+
+void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
+ const DebugNames::NameIndex &ni,
+ llvm::StringRef name) {
+ // Ignore SentinelErrors, log everything else.
+ LLDB_LOG_ERROR(
+ LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS),
+ handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
+ "Failed to parse index entries for index at {1:x}, name {2}: {0}",
+ ni.getUnitOffset(), name);
+}
+
+void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename,
+ DIEArray &offsets) {
+ m_fallback.GetGlobalVariables(basename, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(basename.GetStringRef())) {
+ if (entry.tag() != DW_TAG_variable)
+ continue;
+
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) {
+ m_fallback.GetGlobalVariables(regex, offsets);
+
+ for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
+ for (DebugNames::NameTableEntry nte: ni) {
+ if (!regex.Execute(nte.getString()))
+ continue;
+
+ uint32_t entry_offset = nte.getEntryOffset();
+ llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
+ for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
+ if (entry_or->tag() != DW_TAG_variable)
+ continue;
+
+ Append(*entry_or, offsets);
+ }
+ MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
+ }
+ }
+}
+
+void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
+ DIEArray &offsets) {
+ m_fallback.GetGlobalVariables(cu, offsets);
+
+ uint64_t cu_offset = cu.GetOffset();
+ for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
+ for (DebugNames::NameTableEntry nte: ni) {
+ uint32_t entry_offset = nte.getEntryOffset();
+ llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
+ for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
+ if (entry_or->tag() != DW_TAG_variable)
+ continue;
+ if (entry_or->getCUOffset() != cu_offset)
+ continue;
+
+ Append(*entry_or, offsets);
+ }
+ MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
+ }
+ }
+}
+
+void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) {
+ m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets);
+
+ // Keep a list of incomplete types as fallback for when we don't find the
+ // complete type.
+ DIEArray incomplete_types;
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(class_name.GetStringRef())) {
+ if (entry.tag() != DW_TAG_structure_type &&
+ entry.tag() != DW_TAG_class_type)
+ continue;
+
+ DIERef ref = ToDIERef(entry);
+ if (!ref)
+ continue;
+
+ DWARFUnit *cu = m_debug_info.GetCompileUnit(ref.cu_offset);
+ if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
+ incomplete_types.push_back(ref);
+ continue;
+ }
+
+ // FIXME: We should return DWARFDIEs so we don't have to resolve it twice.
+ DWARFDIE die = m_debug_info.GetDIE(ref);
+ if (!die)
+ continue;
+
+ if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
+ // If we find the complete version we're done.
+ offsets.push_back(ref);
+ return;
+ } else {
+ incomplete_types.push_back(ref);
+ }
+ }
+
+ offsets.insert(offsets.end(), incomplete_types.begin(),
+ incomplete_types.end());
+}
+
+void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
+ m_fallback.GetTypes(name, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(name.GetStringRef())) {
+ if (isType(entry.tag()))
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetTypes(const DWARFDeclContext &context,
+ DIEArray &offsets) {
+ m_fallback.GetTypes(context, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(context[0].name)) {
+ if (entry.tag() == context[0].tag)
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
+ m_fallback.GetNamespaces(name, offsets);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(name.GetStringRef())) {
+ if (entry.tag() == DW_TAG_namespace)
+ Append(entry, offsets);
+ }
+}
+
+void DebugNamesDWARFIndex::GetFunctions(
+ ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+
+ m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, dies);
+
+ for (const DebugNames::Entry &entry :
+ m_debug_names_up->equal_range(name.GetStringRef())) {
+ Tag tag = entry.tag();
+ if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
+ continue;
+
+ if (DIERef ref = ToDIERef(entry))
+ ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx,
+ name_type_mask, dies);
+ }
+}
+
+void DebugNamesDWARFIndex::GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) {
+ m_fallback.GetFunctions(regex, offsets);
+
+ for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
+ for (DebugNames::NameTableEntry nte: ni) {
+ if (!regex.Execute(nte.getString()))
+ continue;
+
+ uint32_t entry_offset = nte.getEntryOffset();
+ llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
+ for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
+ Tag tag = entry_or->tag();
+ if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
+ continue;
+
+ Append(*entry_or, offsets);
+ }
+ MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
+ }
+ }
+}
+
+void DebugNamesDWARFIndex::Dump(Stream &s) {
+ m_fallback.Dump(s);
+
+ std::string data;
+ llvm::raw_string_ostream os(data);
+ m_debug_names_up->dump(os);
+ s.PutCString(os.str());
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
new file mode 100644
index 000000000000..30423c7ca2a2
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h
@@ -0,0 +1,83 @@
+//===-- DebugNamesDWARFIndex.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_DEBUGNAMESDWARFINDEX_H
+#define LLDB_DEBUGNAMESDWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
+#include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
+#include "lldb/Utility/ConstString.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+
+namespace lldb_private {
+class DebugNamesDWARFIndex : public DWARFIndex {
+public:
+ static llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
+ Create(Module &module, DWARFDataExtractor debug_names,
+ DWARFDataExtractor debug_str, DWARFDebugInfo *debug_info);
+
+ void Preload() override { m_fallback.Preload(); }
+
+ void GetGlobalVariables(ConstString basename, DIEArray &offsets) override;
+ void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) override;
+ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override;
+ void GetObjCMethods(ConstString class_name, DIEArray &offsets) override {}
+ void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation,
+ DIEArray &offsets) override;
+ void GetTypes(ConstString name, DIEArray &offsets) override;
+ void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
+ void GetNamespaces(ConstString name, DIEArray &offsets) override;
+ void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) override;
+ void GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) override;
+
+ void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) override {}
+ void Dump(Stream &s) override;
+
+private:
+ DebugNamesDWARFIndex(Module &module,
+ std::unique_ptr<llvm::DWARFDebugNames> debug_names_up,
+ DWARFDataExtractor debug_names_data,
+ DWARFDataExtractor debug_str_data,
+ DWARFDebugInfo &debug_info)
+ : DWARFIndex(module), m_debug_info(debug_info),
+ m_debug_names_data(debug_names_data), m_debug_str_data(debug_str_data),
+ m_debug_names_up(std::move(debug_names_up)),
+ m_fallback(module, &debug_info, GetUnits(*m_debug_names_up)) {}
+
+ DWARFDebugInfo &m_debug_info;
+
+ // LLVM DWARFDebugNames will hold a non-owning reference to this data, so keep
+ // track of the ownership here.
+ DWARFDataExtractor m_debug_names_data;
+ DWARFDataExtractor m_debug_str_data;
+
+ using DebugNames = llvm::DWARFDebugNames;
+ std::unique_ptr<DebugNames> m_debug_names_up;
+ ManualDWARFIndex m_fallback;
+
+ DIERef ToDIERef(const DebugNames::Entry &entry);
+ void Append(const DebugNames::Entry &entry, DIEArray &offsets);
+
+ static void MaybeLogLookupError(llvm::Error error,
+ const DebugNames::NameIndex &ni,
+ llvm::StringRef name);
+
+ static llvm::DenseSet<dw_offset_t> GetUnits(const DebugNames &debug_names);
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_DEBUGNAMESDWARFINDEX_H
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
index cb1e5c185613..36211a08557e 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
@@ -75,15 +75,14 @@ void DWARFMappedHash::ExtractClassOrStructDIEArray(
die_tag == DW_TAG_structure_type) {
if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) {
if (return_implementation_only_if_available) {
- // We found the one true definition for this class, so
- // only return that
+ // We found the one true definition for this class, so only return
+ // that
die_offsets.clear();
die_offsets.emplace_back(die_info_array[i].cu_offset,
die_info_array[i].offset);
return;
} else {
- // Put the one true definition as the first entry so it
- // matches first
+ // Put the one true definition as the first entry so it matches first
die_offsets.emplace(die_offsets.begin(), die_info_array[i].cu_offset,
die_info_array[i].offset);
}
@@ -137,9 +136,8 @@ DWARFMappedHash::DIEInfo::DIEInfo(dw_offset_t c, dw_offset_t o, dw_tag_t t,
DWARFMappedHash::Prologue::Prologue(dw_offset_t _die_base_offset)
: die_base_offset(_die_base_offset), atoms(), atom_mask(0),
min_hash_data_byte_size(0), hash_data_has_fixed_byte_size(true) {
- // Define an array of DIE offsets by first defining an array,
- // and then define the atom type for the array, in this case
- // we have an array of DIE offsets
+ // Define an array of DIE offsets by first defining an array, and then define
+ // the atom type for the array, in this case we have an array of DIE offsets
AppendAtom(eAtomTypeDIEOffset, DW_FORM_data4);
}
@@ -239,8 +237,7 @@ DWARFMappedHash::Prologue::Read(const lldb_private::DataExtractor &data,
size_t DWARFMappedHash::Prologue::GetByteSize() const {
// Add an extra count to the atoms size for the zero termination Atom that
- // gets
- // written to disk
+ // gets written to disk
return sizeof(die_base_offset) + sizeof(uint32_t) +
atoms.size() * sizeof(Atom);
}
@@ -379,17 +376,18 @@ bool DWARFMappedHash::MemoryTable::ReadHashData(uint32_t hash_data_offset,
DWARFMappedHash::MemoryTable::Result
DWARFMappedHash::MemoryTable::GetHashDataForName(
- const char *name, lldb::offset_t *hash_data_offset_ptr, Pair &pair) const {
+ llvm::StringRef name, lldb::offset_t *hash_data_offset_ptr,
+ Pair &pair) const {
pair.key = m_data.GetU32(hash_data_offset_ptr);
pair.value.clear();
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
+ // If the key is zero, this terminates our chain of HashData objects for this
+ // hash value.
if (pair.key == 0)
return eResultEndOfHashData;
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
+ // There definitely should be a string for this string offset, if there
+ // isn't, there is something wrong, return and error
const char *strp_cstr = m_string_table.PeekCStr(pair.key);
if (strp_cstr == NULL) {
*hash_data_offset_ptr = UINT32_MAX;
@@ -402,22 +400,21 @@ DWARFMappedHash::MemoryTable::GetHashDataForName(
if (count > 0 &&
m_data.ValidOffsetForDataOfSize(*hash_data_offset_ptr,
min_total_hash_data_size)) {
- // We have at least one HashData entry, and we have enough
- // data to parse at least "count" HashData entries.
+ // We have at least one HashData entry, and we have enough data to parse at
+ // least "count" HashData entries.
// First make sure the entire C string matches...
- const bool match = strcmp(name, strp_cstr) == 0;
+ const bool match = name == strp_cstr;
if (!match && m_header.header_data.HashDataHasFixedByteSize()) {
- // If the string doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
+ // If the string doesn't match and we have fixed size data, we can just
+ // add the total byte size of all HashData objects to the hash data
+ // offset and be done...
*hash_data_offset_ptr += min_total_hash_data_size;
} else {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
+ // If the string does match, or we don't have fixed size data then we
+ // need to read the hash data as a stream. If the string matches we also
+ // append all HashData objects to the value array.
for (uint32_t i = 0; i < count; ++i) {
DIEInfo die_info;
if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) {
@@ -431,16 +428,15 @@ DWARFMappedHash::MemoryTable::GetHashDataForName(
}
}
}
- // Return the correct response depending on if the string matched
- // or not...
+ // Return the correct response depending on if the string matched or not...
if (match)
return eResultKeyMatch; // The key (cstring) matches and we have lookup
// results!
else
return eResultKeyMismatch; // The key doesn't match, this function will
// get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
+ // again for the next key/value or the key terminator which in our case is
+ // a zero .debug_str offset.
} else {
*hash_data_offset_ptr = UINT32_MAX;
return eResultError;
@@ -452,13 +448,13 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression(
const lldb_private::RegularExpression &regex,
lldb::offset_t *hash_data_offset_ptr, Pair &pair) const {
pair.key = m_data.GetU32(hash_data_offset_ptr);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
+ // If the key is zero, this terminates our chain of HashData objects for this
+ // hash value.
if (pair.key == 0)
return eResultEndOfHashData;
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
+ // There definitely should be a string for this string offset, if there
+ // isn't, there is something wrong, return and error
const char *strp_cstr = m_string_table.PeekCStr(pair.key);
if (strp_cstr == NULL)
return eResultError;
@@ -472,15 +468,14 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression(
const bool match = regex.Execute(llvm::StringRef(strp_cstr));
if (!match && m_header.header_data.HashDataHasFixedByteSize()) {
- // If the regex doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
+ // If the regex doesn't match and we have fixed size data, we can just
+ // add the total byte size of all HashData objects to the hash data
+ // offset and be done...
*hash_data_offset_ptr += min_total_hash_data_size;
} else {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
+ // If the string does match, or we don't have fixed size data then we
+ // need to read the hash data as a stream. If the string matches we also
+ // append all HashData objects to the value array.
for (uint32_t i = 0; i < count; ++i) {
DIEInfo die_info;
if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) {
@@ -494,16 +489,15 @@ DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression(
}
}
}
- // Return the correct response depending on if the string matched
- // or not...
+ // Return the correct response depending on if the string matched or not...
if (match)
return eResultKeyMatch; // The key (cstring) matches and we have lookup
// results!
else
return eResultKeyMismatch; // The key doesn't match, this function will
// get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
+ // again for the next key/value or the key terminator which in our case is
+ // a zero .debug_str offset.
} else {
*hash_data_offset_ptr = UINT32_MAX;
return eResultError;
@@ -528,8 +522,7 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex(
switch (hash_result) {
case eResultKeyMatch:
case eResultKeyMismatch:
- // Whether we matches or not, it doesn't matter, we
- // keep looking.
+ // Whether we matches or not, it doesn't matter, we keep looking.
break;
case eResultEndOfHashData:
@@ -552,8 +545,8 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsInRange(
lldb::offset_t hash_data_offset = GetHashDataOffset(offset_idx);
while (!done && hash_data_offset != UINT32_MAX) {
KeyType key = m_data.GetU32(&hash_data_offset);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
+ // If the key is zero, this terminates our chain of HashData objects for
+ // this hash value.
if (key == 0)
break;
@@ -573,9 +566,9 @@ size_t DWARFMappedHash::MemoryTable::AppendAllDIEsInRange(
return die_info_array.size();
}
-size_t DWARFMappedHash::MemoryTable::FindByName(const char *name,
+size_t DWARFMappedHash::MemoryTable::FindByName(llvm::StringRef name,
DIEArray &die_offsets) {
- if (!name || !name[0])
+ if (name.empty())
return 0;
DIEInfoArray die_info_array;
@@ -584,7 +577,7 @@ size_t DWARFMappedHash::MemoryTable::FindByName(const char *name,
return die_info_array.size();
}
-size_t DWARFMappedHash::MemoryTable::FindByNameAndTag(const char *name,
+size_t DWARFMappedHash::MemoryTable::FindByNameAndTag(llvm::StringRef name,
const dw_tag_t tag,
DIEArray &die_offsets) {
DIEInfoArray die_info_array;
@@ -594,8 +587,8 @@ size_t DWARFMappedHash::MemoryTable::FindByNameAndTag(const char *name,
}
size_t DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash(
- const char *name, const dw_tag_t tag, const uint32_t qualified_name_hash,
- DIEArray &die_offsets) {
+ llvm::StringRef name, const dw_tag_t tag,
+ const uint32_t qualified_name_hash, DIEArray &die_offsets) {
DIEInfoArray die_info_array;
if (FindByName(name, die_info_array))
DWARFMappedHash::ExtractDIEArray(die_info_array, tag, qualified_name_hash,
@@ -604,22 +597,21 @@ size_t DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash(
}
size_t DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName(
- const char *name, DIEArray &die_offsets, bool must_be_implementation) {
+ llvm::StringRef name, DIEArray &die_offsets, bool must_be_implementation) {
DIEInfoArray die_info_array;
if (FindByName(name, die_info_array)) {
if (must_be_implementation &&
GetHeader().header_data.ContainsAtom(eAtomTypeTypeFlags)) {
- // If we have two atoms, then we have the DIE offset and
- // the type flags so we can find the objective C class
- // efficiently.
+ // If we have two atoms, then we have the DIE offset and the type flags
+ // so we can find the objective C class efficiently.
DWARFMappedHash::ExtractTypesFromDIEArray(die_info_array, UINT32_MAX,
eTypeFlagClassIsImplementation,
die_offsets);
} else {
- // We don't only want the one true definition, so try and see
- // what we can find, and only return class or struct DIEs.
- // If we do have the full implementation, then return it alone,
- // else return all possible matches.
+ // We don't only want the one true definition, so try and see what we can
+ // find, and only return class or struct DIEs. If we do have the full
+ // implementation, then return it alone, else return all possible
+ // matches.
const bool return_implementation_only_if_available = true;
DWARFMappedHash::ExtractClassOrStructDIEArray(
die_info_array, return_implementation_only_if_available, die_offsets);
@@ -628,9 +620,9 @@ size_t DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName(
return die_offsets.size();
}
-size_t DWARFMappedHash::MemoryTable::FindByName(const char *name,
+size_t DWARFMappedHash::MemoryTable::FindByName(llvm::StringRef name,
DIEInfoArray &die_info_array) {
- if (!name || !name[0])
+ if (name.empty())
return 0;
Pair kv_pair;
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index 959517529e52..17600df2edd4 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -21,10 +21,6 @@
#include "DWARFFormValue.h"
#include "NameToDIE.h"
-class SymbolFileDWARF;
-class DWARFCompileUnit;
-class DWARFDebugInfoEntry;
-
class DWARFMappedHash {
public:
enum AtomType : uint16_t {
@@ -136,17 +132,17 @@ public:
const uint32_t die_offset_end,
DIEInfoArray &die_info_array) const;
- size_t FindByName(const char *name, DIEArray &die_offsets);
+ size_t FindByName(llvm::StringRef name, DIEArray &die_offsets);
- size_t FindByNameAndTag(const char *name, const dw_tag_t tag,
+ size_t FindByNameAndTag(llvm::StringRef name, const dw_tag_t tag,
DIEArray &die_offsets);
- size_t
- FindByNameAndTagAndQualifiedNameHash(const char *name, const dw_tag_t tag,
- const uint32_t qualified_name_hash,
- DIEArray &die_offsets);
+ size_t FindByNameAndTagAndQualifiedNameHash(
+ llvm::StringRef name, const dw_tag_t tag,
+ const uint32_t qualified_name_hash, DIEArray &die_offsets);
- size_t FindCompleteObjCClassByName(const char *name, DIEArray &die_offsets,
+ size_t FindCompleteObjCClassByName(llvm::StringRef name,
+ DIEArray &die_offsets,
bool must_be_implementation);
protected:
@@ -154,14 +150,14 @@ public:
const lldb_private::RegularExpression &regex,
lldb::offset_t *hash_data_offset_ptr, Pair &pair) const;
- size_t FindByName(const char *name, DIEInfoArray &die_info_array);
+ size_t FindByName(llvm::StringRef name, DIEInfoArray &die_info_array);
- Result GetHashDataForName(const char *name,
+ Result GetHashDataForName(llvm::StringRef name,
lldb::offset_t *hash_data_offset_ptr,
Pair &pair) const override;
- const lldb_private::DWARFDataExtractor &m_data;
- const lldb_private::DWARFDataExtractor &m_string_table;
+ lldb_private::DWARFDataExtractor m_data;
+ lldb_private::DWARFDataExtractor m_string_table;
std::string m_name;
};
diff --git a/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
new file mode 100644
index 000000000000..6438f02fe8ec
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -0,0 +1,488 @@
+//===-- ManualDWARFIndex.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Host/TaskPool.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/Timer.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+void ManualDWARFIndex::Index() {
+ if (!m_debug_info)
+ return;
+
+ DWARFDebugInfo &debug_info = *m_debug_info;
+ m_debug_info = nullptr;
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "%p", static_cast<void *>(&debug_info));
+
+ std::vector<DWARFUnit *> units_to_index;
+ units_to_index.reserve(debug_info.GetNumCompileUnits());
+ for (size_t U = 0; U < debug_info.GetNumCompileUnits(); ++U) {
+ DWARFUnit *unit = debug_info.GetCompileUnitAtIndex(U);
+ if (unit && m_units_to_avoid.count(unit->GetOffset()) == 0)
+ units_to_index.push_back(unit);
+ }
+ if (units_to_index.empty())
+ return;
+
+ std::vector<IndexSet> sets(units_to_index.size());
+
+ //----------------------------------------------------------------------
+ // Keep memory down by clearing DIEs for any compile units if indexing
+ // caused us to load the compile unit's DIEs.
+ //----------------------------------------------------------------------
+ std::vector<llvm::Optional<DWARFUnit::ScopedExtractDIEs>> clear_cu_dies(
+ units_to_index.size());
+ auto parser_fn = [&](size_t cu_idx) {
+ IndexUnit(*units_to_index[cu_idx], sets[cu_idx]);
+ };
+
+ auto extract_fn = [&units_to_index, &clear_cu_dies](size_t cu_idx) {
+ clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped();
+ };
+
+ // Create a task runner that extracts dies for each DWARF compile unit in a
+ // separate thread
+ //----------------------------------------------------------------------
+ // First figure out which compile units didn't have their DIEs already
+ // parsed and remember this. If no DIEs were parsed prior to this index
+ // function call, we are going to want to clear the CU dies after we are
+ // done indexing to make sure we don't pull in all DWARF dies, but we need
+ // to wait until all compile units have been indexed in case a DIE in one
+ // compile unit refers to another and the indexes accesses those DIEs.
+ //----------------------------------------------------------------------
+ TaskMapOverInt(0, units_to_index.size(), extract_fn);
+
+ // Now create a task runner that can index each DWARF compile unit in a
+ // separate thread so we can index quickly.
+
+ TaskMapOverInt(0, units_to_index.size(), parser_fn);
+
+ auto finalize_fn = [this, &sets](NameToDIE(IndexSet::*index)) {
+ NameToDIE &result = m_set.*index;
+ for (auto &set : sets)
+ result.Append(set.*index);
+ result.Finalize();
+ };
+
+ TaskPool::RunTasks([&]() { finalize_fn(&IndexSet::function_basenames); },
+ [&]() { finalize_fn(&IndexSet::function_fullnames); },
+ [&]() { finalize_fn(&IndexSet::function_methods); },
+ [&]() { finalize_fn(&IndexSet::function_selectors); },
+ [&]() { finalize_fn(&IndexSet::objc_class_selectors); },
+ [&]() { finalize_fn(&IndexSet::globals); },
+ [&]() { finalize_fn(&IndexSet::types); },
+ [&]() { finalize_fn(&IndexSet::namespaces); });
+}
+
+void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, IndexSet &set) {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS);
+
+ if (log) {
+ m_module.LogMessage(
+ log, "ManualDWARFIndex::IndexUnit for compile unit at .debug_info[0x%8.8x]",
+ unit.GetOffset());
+ }
+
+ const LanguageType cu_language = unit.GetLanguageType();
+ DWARFFormValue::FixedFormSizes fixed_form_sizes = unit.GetFixedFormSizes();
+
+ IndexUnitImpl(unit, cu_language, fixed_form_sizes, unit.GetOffset(), set);
+
+ SymbolFileDWARFDwo *dwo_symbol_file = unit.GetDwoSymbolFile();
+ if (dwo_symbol_file && dwo_symbol_file->GetCompileUnit()) {
+ IndexUnitImpl(*dwo_symbol_file->GetCompileUnit(), cu_language,
+ fixed_form_sizes, unit.GetOffset(), set);
+ }
+}
+
+void ManualDWARFIndex::IndexUnitImpl(
+ DWARFUnit &unit, const LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
+ const dw_offset_t cu_offset, IndexSet &set) {
+ for (const DWARFDebugInfoEntry &die : unit.dies()) {
+ const dw_tag_t tag = die.Tag();
+
+ switch (tag) {
+ case DW_TAG_array_type:
+ case DW_TAG_base_type:
+ case DW_TAG_class_type:
+ case DW_TAG_constant:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_namespace:
+ case DW_TAG_string_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ case DW_TAG_unspecified_type:
+ case DW_TAG_variable:
+ break;
+
+ default:
+ continue;
+ }
+
+ DWARFAttributes attributes;
+ const char *name = NULL;
+ const char *mangled_cstr = NULL;
+ bool is_declaration = false;
+ // bool is_artificial = false;
+ bool has_address = false;
+ bool has_location_or_const_value = false;
+ bool is_global_or_static_variable = false;
+
+ DWARFFormValue specification_die_form;
+ const size_t num_attributes =
+ die.GetAttributes(&unit, fixed_form_sizes, attributes);
+ if (num_attributes > 0) {
+ for (uint32_t i = 0; i < num_attributes; ++i) {
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ switch (attr) {
+ case DW_AT_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
+ break;
+
+ case DW_AT_declaration:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ is_declaration = form_value.Unsigned() != 0;
+ break;
+
+ // case DW_AT_artificial:
+ // if (attributes.ExtractFormValueAtIndex(i,
+ // form_value))
+ // is_artificial = form_value.Unsigned() != 0;
+ // break;
+
+ case DW_AT_MIPS_linkage_name:
+ case DW_AT_linkage_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ mangled_cstr = form_value.AsCString();
+ break;
+
+ case DW_AT_low_pc:
+ case DW_AT_high_pc:
+ case DW_AT_ranges:
+ has_address = true;
+ break;
+
+ case DW_AT_entry_pc:
+ has_address = true;
+ break;
+
+ case DW_AT_location:
+ case DW_AT_const_value:
+ has_location_or_const_value = true;
+ if (tag == DW_TAG_variable) {
+ const DWARFDebugInfoEntry *parent_die = die.GetParent();
+ while (parent_die != NULL) {
+ switch (parent_die->Tag()) {
+ case DW_TAG_subprogram:
+ case DW_TAG_lexical_block:
+ case DW_TAG_inlined_subroutine:
+ // Even if this is a function level static, we don't add it. We
+ // could theoretically add these if we wanted to by
+ // introspecting into the DW_AT_location and seeing if the
+ // location describes a hard coded address, but we don't want
+ // the performance penalty of that right now.
+ is_global_or_static_variable = false;
+ // if (attributes.ExtractFormValueAtIndex(dwarf, i,
+ // form_value)) {
+ // // If we have valid block data, then we have location
+ // // expression bytesthat are fixed (not a location list).
+ // const uint8_t *block_data = form_value.BlockData();
+ // if (block_data) {
+ // uint32_t block_length = form_value.Unsigned();
+ // if (block_length == 1 +
+ // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) {
+ // if (block_data[0] == DW_OP_addr)
+ // add_die = true;
+ // }
+ // }
+ // }
+ parent_die = NULL; // Terminate the while loop.
+ break;
+
+ case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
+ is_global_or_static_variable = true;
+ parent_die = NULL; // Terminate the while loop.
+ break;
+
+ default:
+ parent_die =
+ parent_die->GetParent(); // Keep going in the while loop.
+ break;
+ }
+ }
+ }
+ break;
+
+ case DW_AT_specification:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ specification_die_form = form_value;
+ break;
+ }
+ }
+ }
+
+ switch (tag) {
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ if (has_address) {
+ if (name) {
+ ObjCLanguage::MethodName objc_method(name, true);
+ if (objc_method.IsValid(true)) {
+ ConstString objc_class_name_with_category(
+ objc_method.GetClassNameWithCategory());
+ ConstString objc_selector_name(objc_method.GetSelector());
+ ConstString objc_fullname_no_category_name(
+ objc_method.GetFullNameWithoutCategory(true));
+ ConstString objc_class_name_no_category(objc_method.GetClassName());
+ set.function_fullnames.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_class_name_with_category)
+ set.objc_class_selectors.Insert(
+ objc_class_name_with_category,
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_class_name_no_category &&
+ objc_class_name_no_category != objc_class_name_with_category)
+ set.objc_class_selectors.Insert(
+ objc_class_name_no_category,
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_selector_name)
+ set.function_selectors.Insert(objc_selector_name,
+ DIERef(cu_offset, die.GetOffset()));
+ if (objc_fullname_no_category_name)
+ set.function_fullnames.Insert(objc_fullname_no_category_name,
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ // If we have a mangled name, then the DW_AT_name attribute is
+ // usually the method name without the class or any parameters
+ bool is_method = DWARFDIE(&unit, &die).IsMethod();
+
+ if (is_method)
+ set.function_methods.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ else
+ set.function_basenames.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+
+ if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
+ set.function_fullnames.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ if (mangled_cstr) {
+ // Make sure our mangled name isn't the same string table entry as
+ // our name. If it starts with '_', then it is ok, else compare the
+ // string to make sure it isn't the same and we don't end up with
+ // duplicate entries
+ if (name && name != mangled_cstr &&
+ ((mangled_cstr[0] == '_') ||
+ (::strcmp(name, mangled_cstr) != 0))) {
+ set.function_fullnames.Insert(ConstString(mangled_cstr),
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_array_type:
+ case DW_TAG_base_type:
+ case DW_TAG_class_type:
+ case DW_TAG_constant:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_string_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subroutine_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ case DW_TAG_unspecified_type:
+ if (name && !is_declaration)
+ set.types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
+ if (mangled_cstr && !is_declaration)
+ set.types.Insert(ConstString(mangled_cstr),
+ DIERef(cu_offset, die.GetOffset()));
+ break;
+
+ case DW_TAG_namespace:
+ if (name)
+ set.namespaces.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ break;
+
+ case DW_TAG_variable:
+ if (name && has_location_or_const_value && is_global_or_static_variable) {
+ set.globals.Insert(ConstString(name),
+ DIERef(cu_offset, die.GetOffset()));
+ // Be sure to include variables by their mangled and demangled names if
+ // they have any since a variable can have a basename "i", a mangled
+ // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name
+ // "(anonymous namespace)::i"...
+
+ // Make sure our mangled name isn't the same string table entry as our
+ // name. If it starts with '_', then it is ok, else compare the string
+ // to make sure it isn't the same and we don't end up with duplicate
+ // entries
+ if (mangled_cstr && name != mangled_cstr &&
+ ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
+ set.globals.Insert(ConstString(mangled_cstr),
+ DIERef(cu_offset, die.GetOffset()));
+ }
+ }
+ break;
+
+ default:
+ continue;
+ }
+ }
+}
+
+void ManualDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) {
+ Index();
+ m_set.globals.Find(basename, offsets);
+}
+
+void ManualDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) {
+ Index();
+ m_set.globals.Find(regex, offsets);
+}
+
+void ManualDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
+ DIEArray &offsets) {
+ Index();
+ m_set.globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets);
+}
+
+void ManualDWARFIndex::GetObjCMethods(ConstString class_name,
+ DIEArray &offsets) {
+ Index();
+ m_set.objc_class_selectors.Find(class_name, offsets);
+}
+
+void ManualDWARFIndex::GetCompleteObjCClass(ConstString class_name,
+ bool must_be_implementation,
+ DIEArray &offsets) {
+ Index();
+ m_set.types.Find(class_name, offsets);
+}
+
+void ManualDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
+ Index();
+ m_set.types.Find(name, offsets);
+}
+
+void ManualDWARFIndex::GetTypes(const DWARFDeclContext &context,
+ DIEArray &offsets) {
+ Index();
+ m_set.types.Find(ConstString(context[0].name), offsets);
+}
+
+void ManualDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
+ Index();
+ m_set.namespaces.Find(name, offsets);
+}
+
+void ManualDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) {
+ Index();
+
+ if (name_type_mask & eFunctionNameTypeFull) {
+ DIEArray offsets;
+ m_set.function_basenames.Find(name, offsets);
+ m_set.function_methods.Find(name, offsets);
+ m_set.function_fullnames.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ DWARFDIE die = info.GetDIE(die_ref);
+ if (!die)
+ continue;
+ if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
+ dies.push_back(die);
+ }
+ }
+ if (name_type_mask & eFunctionNameTypeBase) {
+ DIEArray offsets;
+ m_set.function_basenames.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ DWARFDIE die = info.GetDIE(die_ref);
+ if (!die)
+ continue;
+ if (SymbolFileDWARF::DIEInDeclContext(&parent_decl_ctx, die))
+ dies.push_back(die);
+ }
+ offsets.clear();
+ }
+
+ if (name_type_mask & eFunctionNameTypeMethod && !parent_decl_ctx.IsValid()) {
+ DIEArray offsets;
+ m_set.function_methods.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ if (DWARFDIE die = info.GetDIE(die_ref))
+ dies.push_back(die);
+ }
+ }
+
+ if (name_type_mask & eFunctionNameTypeSelector &&
+ !parent_decl_ctx.IsValid()) {
+ DIEArray offsets;
+ m_set.function_selectors.Find(name, offsets);
+ for (const DIERef &die_ref: offsets) {
+ if (DWARFDIE die = info.GetDIE(die_ref))
+ dies.push_back(die);
+ }
+ }
+}
+
+void ManualDWARFIndex::GetFunctions(const RegularExpression &regex,
+ DIEArray &offsets) {
+ Index();
+
+ m_set.function_basenames.Find(regex, offsets);
+ m_set.function_fullnames.Find(regex, offsets);
+}
+
+void ManualDWARFIndex::Dump(Stream &s) {
+ s.Format("Manual DWARF index for ({0}) '{1:F}':",
+ m_module.GetArchitecture().GetArchitectureName(),
+ m_module.GetObjectFile()->GetFileSpec());
+ s.Printf("\nFunction basenames:\n");
+ m_set.function_basenames.Dump(&s);
+ s.Printf("\nFunction fullnames:\n");
+ m_set.function_fullnames.Dump(&s);
+ s.Printf("\nFunction methods:\n");
+ m_set.function_methods.Dump(&s);
+ s.Printf("\nFunction selectors:\n");
+ m_set.function_selectors.Dump(&s);
+ s.Printf("\nObjective-C class selectors:\n");
+ m_set.objc_class_selectors.Dump(&s);
+ s.Printf("\nGlobals and statics:\n");
+ m_set.globals.Dump(&s);
+ s.Printf("\nTypes:\n");
+ m_set.types.Dump(&s);
+ s.Printf("\nNamespaces:\n");
+ m_set.namespaces.Dump(&s);
+}
diff --git a/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
new file mode 100644
index 000000000000..79ab1d95b380
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -0,0 +1,75 @@
+//===-- ManulaDWARFIndex.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_MANUALDWARFINDEX_H
+#define LLDB_MANUALDWARFINDEX_H
+
+#include "Plugins/SymbolFile/DWARF/DWARFIndex.h"
+#include "Plugins/SymbolFile/DWARF/NameToDIE.h"
+#include "llvm/ADT/DenseSet.h"
+
+namespace lldb_private {
+class ManualDWARFIndex : public DWARFIndex {
+public:
+ ManualDWARFIndex(Module &module, DWARFDebugInfo *debug_info,
+ llvm::DenseSet<dw_offset_t> units_to_avoid = {})
+ : DWARFIndex(module), m_debug_info(debug_info),
+ m_units_to_avoid(std::move(units_to_avoid)) {}
+
+ void Preload() override { Index(); }
+
+ void GetGlobalVariables(ConstString basename, DIEArray &offsets) override;
+ void GetGlobalVariables(const RegularExpression &regex,
+ DIEArray &offsets) override;
+ void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override;
+ void GetObjCMethods(ConstString class_name, DIEArray &offsets) override;
+ void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation,
+ DIEArray &offsets) override;
+ void GetTypes(ConstString name, DIEArray &offsets) override;
+ void GetTypes(const DWARFDeclContext &context, DIEArray &offsets) override;
+ void GetNamespaces(ConstString name, DIEArray &offsets) override;
+ void GetFunctions(ConstString name, DWARFDebugInfo &info,
+ const CompilerDeclContext &parent_decl_ctx,
+ uint32_t name_type_mask,
+ std::vector<DWARFDIE> &dies) override;
+ void GetFunctions(const RegularExpression &regex, DIEArray &offsets) override;
+
+ void ReportInvalidDIEOffset(dw_offset_t offset,
+ llvm::StringRef name) override {}
+ void Dump(Stream &s) override;
+
+private:
+ struct IndexSet {
+ NameToDIE function_basenames;
+ NameToDIE function_fullnames;
+ NameToDIE function_methods;
+ NameToDIE function_selectors;
+ NameToDIE objc_class_selectors;
+ NameToDIE globals;
+ NameToDIE types;
+ NameToDIE namespaces;
+ };
+ void Index();
+ void IndexUnit(DWARFUnit &unit, IndexSet &set);
+
+ static void
+ IndexUnitImpl(DWARFUnit &unit, const lldb::LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
+ const dw_offset_t cu_offset, IndexSet &set);
+
+ /// Non-null value means we haven't built the index yet.
+ DWARFDebugInfo *m_debug_info;
+ /// Which dwarf units should we skip while building the index.
+ llvm::DenseSet<dw_offset_t> m_units_to_avoid;
+
+ IndexSet m_set;
+};
+} // namespace lldb_private
+
+#endif // LLDB_MANUALDWARFINDEX_H
diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index c97680eda0fe..c8d6bba16976 100644
--- a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -14,7 +14,6 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
#include "SymbolFileDWARF.h"
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index f149ec354f08..ac320ac52b08 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -27,6 +27,7 @@
#include "lldb/Utility/Timer.h"
#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
@@ -49,27 +50,24 @@
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
-#include "Plugins/Language/ObjC/ObjCLanguage.h"
-
#include "lldb/Target/Language.h"
-#include "lldb/Host/TaskPool.h"
-
+#include "AppleDWARFIndex.h"
#include "DWARFASTParser.h"
#include "DWARFASTParserClang.h"
-#include "DWARFCompileUnit.h"
#include "DWARFDIECollection.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDebugLine.h"
#include "DWARFDebugMacro.h"
-#include "DWARFDebugPubnames.h"
#include "DWARFDebugRanges.h"
#include "DWARFDeclContext.h"
#include "DWARFFormValue.h"
+#include "DWARFUnit.h"
+#include "DebugNamesDWARFIndex.h"
#include "LogChannelDWARF.h"
+#include "ManualDWARFIndex.h"
#include "SymbolFileDWARFDebugMap.h"
#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDwp.h"
@@ -115,11 +113,20 @@ namespace {
PropertyDefinition g_properties[] = {
{"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr,
- nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic "
- "links will be resolved at DWARF parse time."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ nullptr,
+ "If the DW_AT_comp_dir matches any of these paths the symbolic "
+ "links will be resolved at DWARF parse time."},
+ {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr,
+ nullptr,
+ "Ignore indexes present in the object files and always index DWARF "
+ "manually."},
+ {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr},
+};
-enum { ePropertySymLinkPaths };
+enum {
+ ePropertySymLinkPaths,
+ ePropertyIgnoreIndexes,
+};
class PluginProperties : public Properties {
public:
@@ -139,6 +146,11 @@ public:
assert(option_value);
return option_value->GetCurrentValue();
}
+
+ bool IgnoreFileIndexes() const {
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, ePropertyIgnoreIndexes, false);
+ }
};
typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP;
@@ -165,8 +177,8 @@ static const char *removeHostnameFromPathname(const char *path_from_dwarf) {
return path_from_dwarf;
}
- // check whether we have a windows path, and so the first character
- // is a drive-letter not a hostname.
+ // check whether we have a windows path, and so the first character is a
+ // drive-letter not a hostname.
if (colon_pos == path_from_dwarf + 1 && isalpha(*path_from_dwarf) &&
strlen(path_from_dwarf) > 2 && '\\' == path_from_dwarf[2]) {
return path_from_dwarf;
@@ -175,41 +187,42 @@ static const char *removeHostnameFromPathname(const char *path_from_dwarf) {
return colon_pos + 1;
}
-static const char *resolveCompDir(const char *path_from_dwarf) {
+static FileSpec resolveCompDir(const char *path_from_dwarf) {
if (!path_from_dwarf)
- return nullptr;
+ return FileSpec();
// DWARF2/3 suggests the form hostname:pathname for compilation directory.
// Remove the host part if present.
const char *local_path = removeHostnameFromPathname(path_from_dwarf);
if (!local_path)
- return nullptr;
+ return FileSpec();
bool is_symlink = false;
- FileSpec local_path_spec(local_path, false);
+ // Always normalize our compile unit directory to get rid of redundant
+ // slashes and other path anomalies before we use it for path prepending
+ FileSpec local_spec(local_path, false);
const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i),
- local_path_spec, true);
+ local_spec, true);
if (!is_symlink)
- return local_path;
+ return local_spec;
namespace fs = llvm::sys::fs;
- if (fs::get_file_type(local_path_spec.GetPath(), false) !=
+ if (fs::get_file_type(local_spec.GetPath(), false) !=
fs::file_type::symlink_file)
- return local_path;
+ return local_spec;
- FileSpec resolved_local_path_spec;
- const auto error =
- FileSystem::Readlink(local_path_spec, resolved_local_path_spec);
+ FileSpec resolved_symlink;
+ const auto error = FileSystem::Readlink(local_spec, resolved_symlink);
if (error.Success())
- return resolved_local_path_spec.GetCString();
+ return resolved_symlink;
- return nullptr;
+ return local_spec;
}
-DWARFCompileUnit *SymbolFileDWARF::GetBaseCompileUnit() {
+DWARFUnit *SymbolFileDWARF::GetBaseCompileUnit() {
return nullptr;
}
@@ -334,7 +347,7 @@ size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope,
TypeSet type_set;
CompileUnit *comp_unit = NULL;
- DWARFCompileUnit *dwarf_cu = NULL;
+ DWARFUnit *dwarf_cu = NULL;
if (sc_scope)
comp_unit = sc_scope->CalculateSymbolContextCompileUnit();
@@ -382,6 +395,7 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) {
switch (tag) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_subprogram:
case DW_TAG_inlined_subroutine:
case DW_TAG_lexical_block:
@@ -392,20 +406,16 @@ SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die) {
}
SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile)
- : SymbolFile(objfile), UserID(0), // Used by SymbolFileDWARFDebugMap to when
- // this class parses .o files to contain
- // the .o file index/ID
+ : SymbolFile(objfile), UserID(uint64_t(DW_INVALID_OFFSET)
+ << 32), // Used by SymbolFileDWARFDebugMap to
+ // when this class parses .o files to
+ // contain the .o file index/ID
m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(),
m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(),
m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(),
m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(),
- m_line(), m_apple_names_ap(), m_apple_types_ap(), m_apple_namespaces_ap(),
- m_apple_objc_ap(), m_function_basename_index(),
- m_function_fullname_index(), m_function_method_index(),
- m_function_selector_index(), m_objc_class_selectors_index(),
- m_global_index(), m_type_index(), m_namespace_index(), m_indexed(false),
- m_using_apple_tables(false), m_fetched_external_modules(false),
+ m_line(), m_fetched_external_modules(false),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
m_unique_ast_type_map() {}
@@ -438,6 +448,7 @@ TypeSystem *SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) {
}
void SymbolFileDWARF::InitializeObject() {
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
ModuleSP module_sp(m_obj_file->GetModule());
if (module_sp) {
const SectionList *section_list = module_sp->GetSectionList();
@@ -448,45 +459,38 @@ void SymbolFileDWARF::InitializeObject() {
m_obj_file->ReadSectionData(section, m_dwarf_data);
}
- get_apple_names_data();
- if (m_data_apple_names.m_data.GetByteSize() > 0) {
- m_apple_names_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_names.m_data, get_debug_str_data(), ".apple_names"));
- if (m_apple_names_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_names_ap.reset();
- }
- get_apple_types_data();
- if (m_data_apple_types.m_data.GetByteSize() > 0) {
- m_apple_types_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_types.m_data, get_debug_str_data(), ".apple_types"));
- if (m_apple_types_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_types_ap.reset();
- }
+ if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) {
+ DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
+ LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
+ LoadSectionData(eSectionTypeDWARFAppleNamespaces, apple_namespaces);
+ LoadSectionData(eSectionTypeDWARFAppleTypes, apple_types);
+ LoadSectionData(eSectionTypeDWARFAppleObjC, apple_objc);
- get_apple_namespaces_data();
- if (m_data_apple_namespaces.m_data.GetByteSize() > 0) {
- m_apple_namespaces_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_namespaces.m_data, get_debug_str_data(),
- ".apple_namespaces"));
- if (m_apple_namespaces_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_namespaces_ap.reset();
- }
+ m_index = AppleDWARFIndex::Create(
+ *GetObjectFile()->GetModule(), apple_names, apple_namespaces,
+ apple_types, apple_objc, get_debug_str_data());
- get_apple_objc_data();
- if (m_data_apple_objc.m_data.GetByteSize() > 0) {
- m_apple_objc_ap.reset(new DWARFMappedHash::MemoryTable(
- m_data_apple_objc.m_data, get_debug_str_data(), ".apple_objc"));
- if (m_apple_objc_ap->IsValid())
- m_using_apple_tables = true;
- else
- m_apple_objc_ap.reset();
+ if (m_index)
+ return;
+
+ DWARFDataExtractor debug_names;
+ LoadSectionData(eSectionTypeDWARFDebugNames, debug_names);
+ if (debug_names.GetByteSize() > 0) {
+ llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> index_or =
+ DebugNamesDWARFIndex::Create(*GetObjectFile()->GetModule(),
+ debug_names, get_debug_str_data(),
+ DebugInfo());
+ if (index_or) {
+ m_index = std::move(*index_or);
+ return;
+ }
+ LLDB_LOG_ERROR(log, index_or.takeError(),
+ "Unable to read .debug_names data: {0}");
+ }
}
+
+ m_index = llvm::make_unique<ManualDWARFIndex>(*GetObjectFile()->GetModule(),
+ DebugInfo());
}
bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
@@ -501,15 +505,14 @@ uint32_t SymbolFileDWARF::CalculateAbilities() {
if (section_list == NULL)
return 0;
- // On non Apple platforms we might have .debug_types debug info that
- // is created by using "-fdebug-types-section". LLDB currently will try
- // to load this debug info, but it causes crashes during debugging when
- // types are missing since it doesn't know how to parse the info in
- // the .debug_types type units. This causes all complex debug info
- // types to be unresolved. Because this causes LLDB to crash and since
- // it really doesn't provide a solid debuggiung experience, we should
- // disable trying to debug this kind of DWARF until support gets
- // added or deprecated.
+ // On non Apple platforms we might have .debug_types debug info that is
+ // created by using "-fdebug-types-section". LLDB currently will try to
+ // load this debug info, but it causes crashes during debugging when types
+ // are missing since it doesn't know how to parse the info in the
+ // .debug_types type units. This causes all complex debug info types to be
+ // unresolved. Because this causes LLDB to crash and since it really
+ // doesn't provide a solid debuggiung experience, we should disable trying
+ // to debug this kind of DWARF until support gets added or deprecated.
if (section_list->FindSectionByName(ConstString(".debug_types"))) {
m_obj_file->GetModule()->ReportWarning(
"lldb doesn’t support .debug_types debug info");
@@ -561,10 +564,10 @@ uint32_t SymbolFileDWARF::CalculateAbilities() {
if (symfile_dir_cstr) {
if (strcasestr(symfile_dir_cstr, ".dsym")) {
if (m_obj_file->GetType() == ObjectFile::eTypeDebugInfo) {
- // We have a dSYM file that didn't have a any debug info.
- // If the string table has a size of 1, then it was made from
- // an executable with no debug info, or from an executable that
- // was stripped.
+ // We have a dSYM file that didn't have a any debug info. If the
+ // string table has a size of 1, then it was made from an
+ // executable with no debug info, or from an executable that was
+ // stripped.
section =
section_list->FindSectionByType(eSectionTypeDWARFDebugStr, true)
.get();
@@ -664,6 +667,10 @@ const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_offsets_data() {
m_data_debug_str_offsets);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_types_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugTypes, m_data_debug_types);
+}
+
const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() {
return GetCachedSectionData(eSectionTypeDWARFAppleNames, m_data_apple_names);
}
@@ -681,6 +688,11 @@ const DWARFDataExtractor &SymbolFileDWARF::get_apple_objc_data() {
return GetCachedSectionData(eSectionTypeDWARFAppleObjC, m_data_apple_objc);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_gnu_debugaltlink() {
+ return GetCachedSectionData(eSectionTypeDWARFGNUDebugAltLink,
+ m_data_gnu_debugaltlink);
+}
+
DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
if (m_abbr.get() == NULL) {
const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data();
@@ -716,17 +728,17 @@ const DWARFDebugInfo *SymbolFileDWARF::DebugInfo() const {
return m_info.get();
}
-DWARFCompileUnit *
+DWARFUnit *
SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) {
if (!comp_unit)
return nullptr;
DWARFDebugInfo *info = DebugInfo();
if (info) {
- // Just a normal DWARF file whose user ID for the compile unit is
- // the DWARF offset itself
+ // Just a normal DWARF file whose user ID for the compile unit is the DWARF
+ // offset itself
- DWARFCompileUnit *dwarf_cu =
+ DWARFUnit *dwarf_cu =
info->GetCompileUnit((dw_offset_t)comp_unit->GetID());
if (dwarf_cu && dwarf_cu->GetUserData() == NULL)
dwarf_cu->SetUserData(comp_unit);
@@ -753,7 +765,7 @@ const DWARFDebugRanges *SymbolFileDWARF::DebugRanges() const {
return m_ranges.get();
}
-lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) {
CompUnitSP cu_sp;
if (dwarf_cu) {
@@ -772,13 +784,13 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
} else {
ModuleSP module_sp(m_obj_file->GetModule());
if (module_sp) {
- const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE cu_die = dwarf_cu->DIE();
if (cu_die) {
FileSpec cu_file_spec{cu_die.GetName(), false};
if (cu_file_spec) {
// If we have a full path to the compile unit, we don't need to
- // resolve
- // the file. This can be expensive e.g. when the source files are
+ // resolve the file. This can be expensive e.g. when the source
+ // files are
// NFS mounted.
if (cu_file_spec.IsRelative()) {
const char *cu_comp_dir{
@@ -789,10 +801,11 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
std::string remapped_file;
if (module_sp->RemapSourceFile(cu_file_spec.GetPath(),
remapped_file))
- cu_file_spec.SetFile(remapped_file, false);
+ cu_file_spec.SetFile(remapped_file, false,
+ FileSpec::Style::native);
}
- LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(
+ LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF(
cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
bool is_optimized = dwarf_cu->GetIsOptimized();
@@ -801,10 +814,8 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
cu_language, is_optimized ? eLazyBoolYes : eLazyBoolNo));
if (cu_sp) {
// If we just created a compile unit with an invalid file spec,
- // try and get the
- // first entry in the supports files from the line table as that
- // should be the
- // compile unit.
+ // try and get the first entry in the supports files from the
+ // line table as that should be the compile unit.
if (!cu_file_spec) {
cu_file_spec = cu_sp->GetSupportFiles().GetFileSpecAtIndex(1);
if (cu_file_spec) {
@@ -843,7 +854,7 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
CompUnitSP cu_sp;
DWARFDebugInfo *info = DebugInfo();
if (info) {
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu)
cu_sp = ParseCompileUnit(dwarf_cu, cu_idx);
}
@@ -876,7 +887,7 @@ bool SymbolFileDWARF::FixupAddress(Address &addr) {
lldb::LanguageType
SymbolFileDWARF::ParseCompileUnitLanguage(const SymbolContext &sc) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
return dwarf_cu->GetLanguageType();
else
@@ -886,7 +897,7 @@ SymbolFileDWARF::ParseCompileUnitLanguage(const SymbolContext &sc) {
size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
assert(sc.comp_unit);
size_t functions_added = 0;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
DWARFDIECollection function_dies;
const size_t num_functions =
@@ -907,12 +918,12 @@ size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
bool SymbolFileDWARF::ParseCompileUnitSupportFiles(
const SymbolContext &sc, FileSpecList &support_files) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
- const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE cu_die = dwarf_cu->GetUnitDIEOnly();
if (cu_die) {
- const char *cu_comp_dir = resolveCompDir(
+ FileSpec cu_comp_dir = resolveCompDir(
cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(
DW_AT_stmt_list, DW_INVALID_OFFSET);
@@ -931,7 +942,7 @@ bool SymbolFileDWARF::ParseCompileUnitSupportFiles(
bool SymbolFileDWARF::ParseCompileUnitIsOptimized(
const lldb_private::SymbolContext &sc) {
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
return dwarf_cu->GetIsOptimized();
return false;
@@ -941,14 +952,14 @@ bool SymbolFileDWARF::ParseImportedModules(
const lldb_private::SymbolContext &sc,
std::vector<lldb_private::ConstString> &imported_modules) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
if (ClangModulesDeclVendor::LanguageSupportsClangModules(
sc.comp_unit->GetLanguage())) {
UpdateExternalModuleListIfNeeded();
if (sc.comp_unit) {
- const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE die = dwarf_cu->DIE();
if (die) {
for (DWARFDIE child_die = die.GetFirstChild(); child_die;
@@ -998,8 +1009,7 @@ static void ParseDWARFLineTableCallback(dw_offset_t offset,
(ParseDWARFLineTableCallbackInfo *)userData;
LineTable *line_table = info->line_table;
- // If this is our first time here, we need to create a
- // sequence container.
+ // If this is our first time here, we need to create a sequence container.
if (!info->sequence_ap.get()) {
info->sequence_ap.reset(line_table->CreateLineSequenceContainer());
assert(info->sequence_ap.get());
@@ -1022,9 +1032,9 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
if (sc.comp_unit->GetLineTable() != NULL)
return true;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
- const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
if (dwarf_cu_die) {
const dw_offset_t cu_line_offset =
dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list,
@@ -1063,10 +1073,10 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
&info);
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile) {
- // We have an object file that has a line table with addresses
- // that are not linked. We need to link the line table and convert
- // the addresses that are relative to the .o file into addresses
- // for the main executable.
+ // We have an object file that has a line table with addresses that
+ // are not linked. We need to link the line table and convert the
+ // addresses that are relative to the .o file into addresses for
+ // the main executable.
sc.comp_unit->SetLineTable(
debug_map_symfile->LinkOSOLineTable(this, line_table_ap.get()));
} else {
@@ -1105,11 +1115,11 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) {
bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
assert(sc.comp_unit);
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu == nullptr)
return false;
- const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
if (!dwarf_cu_die)
return false;
@@ -1142,9 +1152,9 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
case DW_TAG_lexical_block: {
Block *block = NULL;
if (tag == DW_TAG_subprogram) {
- // Skip any DW_TAG_subprogram DIEs that are inside
- // of a normal or inlined functions. These will be
- // parsed on their own as separate entities.
+ // Skip any DW_TAG_subprogram DIEs that are inside of a normal or
+ // inlined functions. These will be parsed on their own as separate
+ // entities.
if (depth > 0)
break;
@@ -1172,18 +1182,14 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
assert(subprogram_low_pc == LLDB_INVALID_ADDRESS);
subprogram_low_pc = ranges.GetMinRangeBase(0);
} else if (tag == DW_TAG_inlined_subroutine) {
- // We get called here for inlined subroutines in two ways.
- // The first time is when we are making the Function object
- // for this inlined concrete instance. Since we're creating a top
- // level block at
+ // We get called here for inlined subroutines in two ways. The first
+ // time is when we are making the Function object for this inlined
+ // concrete instance. Since we're creating a top level block at
// here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS. So we
- // need to
- // adjust the containing address.
- // The second time is when we are parsing the blocks inside the
- // function that contains
- // the inlined concrete instance. Since these will be blocks inside
- // the containing "real"
- // function the offset will be for that function.
+ // need to adjust the containing address. The second time is when we
+ // are parsing the blocks inside the function that contains the
+ // inlined concrete instance. Since these will be blocks inside the
+ // containing "real" function the offset will be for that function.
if (subprogram_low_pc == LLDB_INVALID_ADDRESS) {
subprogram_low_pc = ranges.GetMinRangeBase(0);
}
@@ -1238,9 +1244,9 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
break;
}
- // Only parse siblings of the block if we are not at depth zero. A depth
- // of zero indicates we are currently parsing the top level
- // DW_TAG_subprogram DIE
+ // Only parse siblings of the block if we are not at depth zero. A depth of
+ // zero indicates we are currently parsing the top level DW_TAG_subprogram
+ // DIE
if (depth == 0)
die.Clear();
@@ -1286,12 +1292,12 @@ void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) {
}
SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) {
- // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API
- // we must make sure we use the correct DWARF file when resolving things.
- // On MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
- // SymbolFileDWARF classes, one for each .o file. We can often end up
- // with references to other DWARF objects and we must be ready to receive
- // a "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
+ // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
+ // must make sure we use the correct DWARF file when resolving things. On
+ // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
+ // SymbolFileDWARF classes, one for each .o file. We can often end up with
+ // references to other DWARF objects and we must be ready to receive a
+ // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
// instance.
SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile();
if (debug_map)
@@ -1302,12 +1308,12 @@ SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) {
DWARFDIE
SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) {
- // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API
- // we must make sure we use the correct DWARF file when resolving things.
- // On MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
- // SymbolFileDWARF classes, one for each .o file. We can often end up
- // with references to other DWARF objects and we must be ready to receive
- // a "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
+ // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
+ // must make sure we use the correct DWARF file when resolving things. On
+ // MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
+ // SymbolFileDWARF classes, one for each .o file. We can often end up with
+ // references to other DWARF objects and we must be ready to receive a
+ // "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF
// instance.
SymbolFileDWARF *dwarf = GetDWARFForUID(uid);
if (dwarf)
@@ -1316,9 +1322,9 @@ SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) {
}
CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE die = GetDIEFromUID(type_uid);
if (die)
return die.GetDecl();
@@ -1327,9 +1333,9 @@ CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
CompilerDeclContext
SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE die = GetDIEFromUID(type_uid);
if (die)
return die.GetDeclContext();
@@ -1338,9 +1344,9 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
CompilerDeclContext
SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE die = GetDIEFromUID(type_uid);
if (die)
return die.GetContainingDeclContext();
@@ -1348,9 +1354,9 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
}
Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
- // Anytime we have a lldb::user_id_t, we must get the DIE by
- // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside
- // the SymbolFileDWARF::GetDIEFromUID() for details.
+ // Anytime we have a lldb::user_id_t, we must get the DIE by calling
+ // SymbolFileDWARF::GetDIEFromUID(). See comments inside the
+ // SymbolFileDWARF::GetDIEFromUID() for details.
DWARFDIE type_die = GetDIEFromUID(type_uid);
if (type_die)
return type_die.ResolveType();
@@ -1371,9 +1377,9 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die,
log, "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
- // We might be coming in in the middle of a type tree (a class
- // within a class, an enum within a class), so parse any needed
- // parent DIEs before we get to this one...
+ // We might be coming in in the middle of a type tree (a class within a
+ // class, an enum within a class), so parse any needed parent DIEs before
+ // we get to this one...
DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(die);
if (decl_ctx_die) {
if (log) {
@@ -1401,8 +1407,8 @@ Type *SymbolFileDWARF::ResolveTypeUID(const DWARFDIE &die,
}
// This function is used when SymbolFileDWARFDebugMap owns a bunch of
-// SymbolFileDWARF objects to detect if this DWARF file is the one that
-// can resolve a compiler_type.
+// SymbolFileDWARF objects to detect if this DWARF file is the one that can
+// resolve a compiler_type.
bool SymbolFileDWARF::HasForwardDeclForClangType(
const CompilerType &compiler_type) {
CompilerType compiler_type_no_qualifiers =
@@ -1448,12 +1454,10 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
DWARFDIE dwarf_die = GetDIE(die_it->getSecond());
if (dwarf_die) {
- // Once we start resolving this type, remove it from the forward declaration
- // map in case anyone child members or other types require this type to get
- // resolved.
- // The type will get resolved when all of the calls to
- // SymbolFileDWARF::ResolveClangOpaqueTypeDefinition
- // are done.
+ // Once we start resolving this type, remove it from the forward
+ // declaration map in case anyone child members or other types require this
+ // type to get resolved. The type will get resolved when all of the calls
+ // to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition are done.
GetForwardDeclClangTypeToDie().erase(die_it);
Type *type = GetDIEToType().lookup(dwarf_die.GetDIE());
@@ -1494,12 +1498,12 @@ Type *SymbolFileDWARF::ResolveType(const DWARFDIE &die,
}
CompileUnit *
-SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu,
+SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) {
// Check if the symbol vendor already knows about this compile unit?
if (dwarf_cu->GetUserData() == NULL) {
- // The symbol vendor doesn't know about this compile unit, we
- // need to parse and add it to the symbol vendor object.
+ // The symbol vendor doesn't know about this compile unit, we need to parse
+ // and add it to the symbol vendor object.
return ParseCompileUnit(dwarf_cu, cu_idx).get();
}
return (CompileUnit *)dwarf_cu->GetUserData();
@@ -1508,15 +1512,7 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu,
size_t SymbolFileDWARF::GetObjCMethodDIEOffsets(ConstString class_name,
DIEArray &method_die_offsets) {
method_die_offsets.clear();
- if (m_using_apple_tables) {
- if (m_apple_objc_ap.get())
- m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
- } else {
- if (!m_indexed)
- Index();
-
- m_objc_class_selectors_index.Find(class_name, method_die_offsets);
- }
+ m_index->GetObjCMethods(class_name, method_die_offsets);
return method_die_offsets.size();
}
@@ -1560,9 +1556,9 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
- DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) {
+ DWARFUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) {
// If we are using a dSYM file, we never want the standard DWO files since
- // the -gmodule support uses the same DWO machanism to specify full debug
+ // the -gmodules support uses the same DWO machanism to specify full debug
// info files for modules.
if (GetDebugMapSymfile())
return nullptr;
@@ -1589,7 +1585,7 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
if (!comp_dir)
return nullptr;
- dwo_file.SetFile(comp_dir, true);
+ dwo_file.SetFile(comp_dir, true, FileSpec::Style::native);
dwo_file.AppendPathComponent(dwo_name);
}
@@ -1617,9 +1613,9 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
if (die && die.HasChildren() == false) {
const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
@@ -1632,35 +1628,35 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
if (dwo_path) {
ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, false,
+ FileSpec::Style::native);
if (dwo_module_spec.GetFileSpec().IsRelative()) {
const char *comp_dir =
die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
if (comp_dir) {
- dwo_module_spec.GetFileSpec().SetFile(comp_dir, true);
+ dwo_module_spec.GetFileSpec().SetFile(comp_dir, true,
+ FileSpec::Style::native);
dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
}
}
dwo_module_spec.GetArchitecture() =
m_obj_file->GetModule()->GetArchitecture();
- // When LLDB loads "external" modules it looks at the
- // presence of DW_AT_GNU_dwo_name.
- // However, when the already created module
- // (corresponding to .dwo itself) is being processed,
- // it will see the presence of DW_AT_GNU_dwo_name
- // (which contains the name of dwo file) and
- // will try to call ModuleList::GetSharedModule again.
- // In some cases (i.e. for empty files) Clang 4.0
- // generates a *.dwo file which has DW_AT_GNU_dwo_name,
- // but no DW_AT_comp_dir. In this case the method
- // ModuleList::GetSharedModule will fail and
- // the warning will be printed. However, as one can notice
- // in this case we don't actually need to try to load the already
- // loaded module (corresponding to .dwo) so we simply skip it.
+ // When LLDB loads "external" modules it looks at the presence of
+ // DW_AT_GNU_dwo_name. However, when the already created module
+ // (corresponding to .dwo itself) is being processed, it will see
+ // the presence of DW_AT_GNU_dwo_name (which contains the name of
+ // dwo file) and will try to call ModuleList::GetSharedModule
+ // again. In some cases (i.e. for empty files) Clang 4.0 generates
+ // a *.dwo file which has DW_AT_GNU_dwo_name, but no
+ // DW_AT_comp_dir. In this case the method
+ // ModuleList::GetSharedModule will fail and the warning will be
+ // printed. However, as one can notice in this case we don't
+ // actually need to try to load the already loaded module
+ // (corresponding to .dwo) so we simply skip it.
if (m_obj_file->GetFileSpec()
.GetFileNameExtension()
- .GetStringRef() == "dwo" &&
+ .GetStringRef() == ".dwo" &&
llvm::StringRef(m_obj_file->GetFileSpec().GetPath())
.endswith(dwo_module_spec.GetFileSpec().GetPath())) {
continue;
@@ -1751,13 +1747,11 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
const dw_offset_t cu_offset =
debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr);
if (cu_offset == DW_INVALID_OFFSET) {
- // Global variables are not in the compile unit address ranges. The only
- // way to
- // currently find global variables is to iterate over the
- // .debug_pubnames or the
- // __apple_names table and find all items in there that point to
- // DW_TAG_variable
- // DIEs and then find the address that matches.
+ // Global variables are not in the compile unit address ranges. The
+ // only way to currently find global variables is to iterate over the
+ // .debug_pubnames or the __apple_names table and find all items in
+ // there that point to DW_TAG_variable DIEs and then find the address
+ // that matches.
if (resolve_scope & eSymbolContextVariable) {
GlobalVariableMap &map = GetGlobalAranges();
const GlobalVariableMap::Entry *entry =
@@ -1774,7 +1768,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
}
} else {
uint32_t cu_idx = DW_INVALID_INDEX;
- DWARFCompileUnit *dwarf_cu =
+ DWARFUnit *dwarf_cu =
debug_info->GetCompileUnit(cu_offset, &cu_idx);
if (dwarf_cu) {
sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
@@ -1825,13 +1819,10 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table != NULL) {
// And address that makes it into this function should be in
- // terms
- // of this debug file if there is no debug map, or it will be an
- // address in the .o file which needs to be fixed up to be in
- // terms
- // of the debug map executable. Either way, calling
- // FixupAddress()
- // will work for us.
+ // terms of this debug file if there is no debug map, or it
+ // will be an address in the .o file which needs to be fixed up
+ // to be in terms of the debug map executable. Either way,
+ // calling FixupAddress() will work for us.
Address exe_so_addr(so_addr);
if (FixupAddress(exe_so_addr)) {
if (line_table->FindLineEntryByAddress(exe_so_addr,
@@ -1845,11 +1836,11 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
if (force_check_line_table &&
!(resolved & eSymbolContextLineEntry)) {
// We might have had a compile unit that had discontiguous
- // address ranges where the gaps are symbols that don't have
- // any debug info. Discontiguous compile unit address ranges
- // should only happen when there aren't other functions from
- // other compile units in these gaps. This helps keep the size
- // of the aranges down.
+ // address ranges where the gaps are symbols that don't have any
+ // debug info. Discontiguous compile unit address ranges should
+ // only happen when there aren't other functions from other
+ // compile units in these gaps. This helps keep the size of the
+ // aranges down.
sc.comp_unit = NULL;
resolved &= ~eSymbolContextCompUnit;
}
@@ -1876,7 +1867,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
DWARFDebugInfo *debug_info = DebugInfo();
if (debug_info) {
uint32_t cu_idx;
- DWARFCompileUnit *dwarf_cu = NULL;
+ DWARFUnit *dwarf_cu = NULL;
for (cu_idx = 0;
(dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL;
@@ -1891,8 +1882,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
if (sc.comp_unit) {
uint32_t file_idx = UINT32_MAX;
- // If we are looking for inline functions only and we don't
- // find it in the support files, we are done.
+ // If we are looking for inline functions only and we don't find it
+ // in the support files, we are done.
if (check_inlines) {
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
1, file_spec, true);
@@ -1904,8 +1895,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table != NULL && line != 0) {
- // We will have already looked up the file index if
- // we are searching for inline entries.
+ // We will have already looked up the file index if we are
+ // searching for inline entries.
if (!check_inlines)
file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex(
1, file_spec, true);
@@ -1962,16 +1953,14 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
}
} else if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call
- // sites
- // by file and line and if the file spec matches that of the
- // compile unit
+ // sites by file and line and if the file spec matches that of
+ // the compile unit
sc_list.Append(sc);
}
} else if (file_spec_matches_cu_file_spec && !check_inlines) {
// only append the context if we aren't looking for inline call
- // sites
- // by file and line and if the file spec matches that of the
- // compile unit
+ // sites by file and line and if the file spec matches that of
+ // the compile unit
sc_list.Append(sc);
}
@@ -1988,143 +1977,15 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
void SymbolFileDWARF::PreloadSymbols() {
std::lock_guard<std::recursive_mutex> guard(
GetObjectFile()->GetModule()->GetMutex());
- Index();
-}
-
-void SymbolFileDWARF::Index() {
- if (m_indexed)
- return;
- m_indexed = true;
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(
- func_cat, "SymbolFileDWARF::Index (%s)",
- GetObjectFile()->GetFileSpec().GetFilename().AsCString("<Unknown>"));
-
- DWARFDebugInfo *debug_info = DebugInfo();
- if (debug_info) {
- const uint32_t num_compile_units = GetNumCompileUnits();
- if (num_compile_units == 0)
- return;
-
- std::vector<NameToDIE> function_basename_index(num_compile_units);
- std::vector<NameToDIE> function_fullname_index(num_compile_units);
- std::vector<NameToDIE> function_method_index(num_compile_units);
- std::vector<NameToDIE> function_selector_index(num_compile_units);
- std::vector<NameToDIE> objc_class_selectors_index(num_compile_units);
- std::vector<NameToDIE> global_index(num_compile_units);
- std::vector<NameToDIE> type_index(num_compile_units);
- std::vector<NameToDIE> namespace_index(num_compile_units);
-
- // std::vector<bool> might be implemented using bit test-and-set, so use
- // uint8_t instead.
- std::vector<uint8_t> clear_cu_dies(num_compile_units, false);
- auto parser_fn = [debug_info, &function_basename_index,
- &function_fullname_index, &function_method_index,
- &function_selector_index, &objc_class_selectors_index,
- &global_index, &type_index,
- &namespace_index](size_t cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- if (dwarf_cu) {
- dwarf_cu->Index(
- function_basename_index[cu_idx], function_fullname_index[cu_idx],
- function_method_index[cu_idx], function_selector_index[cu_idx],
- objc_class_selectors_index[cu_idx], global_index[cu_idx],
- type_index[cu_idx], namespace_index[cu_idx]);
- }
- };
-
- auto extract_fn = [debug_info, &clear_cu_dies](size_t cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- if (dwarf_cu) {
- // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the
- // DIEs for a compile unit have already been parsed.
- if (dwarf_cu->ExtractDIEsIfNeeded(false) > 1)
- clear_cu_dies[cu_idx] = true;
- }
- };
-
- // Create a task runner that extracts dies for each DWARF compile unit in a
- // separate thread
- //----------------------------------------------------------------------
- // First figure out which compile units didn't have their DIEs already
- // parsed and remember this. If no DIEs were parsed prior to this index
- // function call, we are going to want to clear the CU dies after we
- // are done indexing to make sure we don't pull in all DWARF dies, but
- // we need to wait until all compile units have been indexed in case
- // a DIE in one compile unit refers to another and the indexes accesses
- // those DIEs.
- //----------------------------------------------------------------------
- TaskMapOverInt(0, num_compile_units, extract_fn);
-
- // Now create a task runner that can index each DWARF compile unit in a
- // separate
- // thread so we can index quickly.
-
- TaskMapOverInt(0, num_compile_units, parser_fn);
-
- auto finalize_fn = [](NameToDIE &index, std::vector<NameToDIE> &srcs) {
- for (auto &src : srcs)
- index.Append(src);
- index.Finalize();
- };
-
- TaskPool::RunTasks(
- [&]() {
- finalize_fn(m_function_basename_index, function_basename_index);
- },
- [&]() {
- finalize_fn(m_function_fullname_index, function_fullname_index);
- },
- [&]() { finalize_fn(m_function_method_index, function_method_index); },
- [&]() {
- finalize_fn(m_function_selector_index, function_selector_index);
- },
- [&]() {
- finalize_fn(m_objc_class_selectors_index, objc_class_selectors_index);
- },
- [&]() { finalize_fn(m_global_index, global_index); },
- [&]() { finalize_fn(m_type_index, type_index); },
- [&]() { finalize_fn(m_namespace_index, namespace_index); });
-
- //----------------------------------------------------------------------
- // Keep memory down by clearing DIEs for any compile units if indexing
- // caused us to load the compile unit's DIEs.
- //----------------------------------------------------------------------
- for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- if (clear_cu_dies[cu_idx])
- debug_info->GetCompileUnitAtIndex(cu_idx)->ClearDIEs(true);
- }
-
-#if defined(ENABLE_DEBUG_PRINTF)
- StreamFile s(stdout, false);
- s.Printf("DWARF index for '%s':",
- GetObjectFile()->GetFileSpec().GetPath().c_str());
- s.Printf("\nFunction basenames:\n");
- m_function_basename_index.Dump(&s);
- s.Printf("\nFunction fullnames:\n");
- m_function_fullname_index.Dump(&s);
- s.Printf("\nFunction methods:\n");
- m_function_method_index.Dump(&s);
- s.Printf("\nFunction selectors:\n");
- m_function_selector_index.Dump(&s);
- s.Printf("\nObjective C class selectors:\n");
- m_objc_class_selectors_index.Dump(&s);
- s.Printf("\nGlobals and statics:\n");
- m_global_index.Dump(&s);
- s.Printf("\nTypes:\n");
- m_type_index.Dump(&s);
- s.Printf("\nNamespaces:\n");
- m_namespace_index.Dump(&s);
-#endif
- }
+ m_index->Preload();
}
bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
const lldb_private::CompilerDeclContext *decl_ctx) {
if (decl_ctx == nullptr || !decl_ctx->IsValid()) {
- // Invalid namespace decl which means we aren't matching only things
- // in this symbol file, so return true to indicate it matches this
- // symbol file.
+ // Invalid namespace decl which means we aren't matching only things in
+ // this symbol file, so return true to indicate it matches this symbol
+ // file.
return true;
}
@@ -2146,14 +2007,15 @@ bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
uint32_t SymbolFileDWARF::FindGlobalVariables(
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches, VariableList &variables) {
+ uint32_t max_matches, VariableList &variables) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log)
GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
- "parent_decl_ctx=%p, append=%u, max_matches=%u, variables)",
- name.GetCString(), static_cast<const void *>(parent_decl_ctx), append,
+ log,
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
+ "parent_decl_ctx=%p, max_matches=%u, variables)",
+ name.GetCString(), static_cast<const void *>(parent_decl_ctx),
max_matches);
if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
@@ -2163,42 +2025,28 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
if (info == NULL)
return 0;
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
- DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
- const char *name_cstr = name.GetCString();
- llvm::StringRef basename;
- llvm::StringRef context;
-
- if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context,
- basename))
- basename = name_cstr;
+ llvm::StringRef basename;
+ llvm::StringRef context;
- m_apple_names_ap->FindByName(basename.data(), die_offsets);
- }
- } else {
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
-
- m_global_index.Find(name, die_offsets);
- }
+ if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetCString(),
+ context, basename))
+ basename = name.GetStringRef();
+ DIEArray die_offsets;
+ m_index->GetGlobalVariables(ConstString(basename), die_offsets);
const size_t num_die_matches = die_offsets.size();
if (num_die_matches) {
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
assert(sc.module_sp);
+ // Loop invariant: Variables up to this index have been checked for context
+ // matches.
+ uint32_t pruned_idx = original_size;
+
bool done = false;
for (size_t i = 0; i < num_die_matches && !done; ++i) {
const DIERef &die_ref = die_offsets[i];
@@ -2229,18 +2077,21 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false,
&variables);
+ while (pruned_idx < variables.GetSize()) {
+ VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx);
+ if (var_sp->GetName().GetStringRef().contains(name.GetStringRef()))
+ ++pruned_idx;
+ else
+ variables.RemoveVariableAtIndex(pruned_idx);
+ }
if (variables.GetSize() - original_size >= max_matches)
done = true;
} break;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
}
@@ -2249,54 +2100,37 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(
const uint32_t num_matches = variables.GetSize() - original_size;
if (log && num_matches > 0) {
GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
- "parent_decl_ctx=%p, append=%u, max_matches=%u, variables) => %u",
- name.GetCString(), static_cast<const void *>(parent_decl_ctx), append,
+ log,
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", "
+ "parent_decl_ctx=%p, max_matches=%u, variables) => %u",
+ name.GetCString(), static_cast<const void *>(parent_decl_ctx),
max_matches, num_matches);
}
return num_matches;
}
uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
VariableList &variables) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log) {
GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, "
- "max_matches=%u, variables)",
- regex.GetText().str().c_str(), append, max_matches);
+ log,
+ "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", "
+ "max_matches=%u, variables)",
+ regex.GetText().str().c_str(), max_matches);
}
DWARFDebugInfo *info = DebugInfo();
if (info == NULL)
return 0;
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
- DWARFMappedHash::DIEInfoArray hash_data_array;
- if (m_apple_names_ap->AppendAllDIEsThatMatchingRegex(regex,
- hash_data_array))
- DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
- }
- } else {
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
-
- m_global_index.Find(regex, die_offsets);
- }
+ m_index->GetGlobalVariables(regex, die_offsets);
SymbolContext sc;
sc.module_sp = m_obj_file->GetModule();
@@ -2315,14 +2149,8 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
if (variables.GetSize() - original_size >= max_matches)
break;
- } else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for regex '%s')\n",
- die_ref.die_offset, regex.GetText().str().c_str());
- }
- }
+ } else
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset, regex.GetText());
}
}
@@ -2330,13 +2158,6 @@ uint32_t SymbolFileDWARF::FindGlobalVariables(const RegularExpression &regex,
return variables.GetSize() - original_size;
}
-bool SymbolFileDWARF::ResolveFunction(const DIERef &die_ref,
- bool include_inlines,
- SymbolContextList &sc_list) {
- DWARFDIE die = DebugInfo()->GetDIE(die_ref);
- return ResolveFunction(die, include_inlines, sc_list);
-}
-
bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
bool include_inlines,
SymbolContextList &sc_list) {
@@ -2390,54 +2211,11 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
return false;
}
-void SymbolFileDWARF::FindFunctions(const ConstString &name,
- const NameToDIE &name_to_die,
- bool include_inlines,
- SymbolContextList &sc_list) {
- DIEArray die_offsets;
- if (name_to_die.Find(name, die_offsets)) {
- ParseFunctions(die_offsets, include_inlines, sc_list);
- }
-}
-
-void SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
- const NameToDIE &name_to_die,
- bool include_inlines,
- SymbolContextList &sc_list) {
- DIEArray die_offsets;
- if (name_to_die.Find(regex, die_offsets)) {
- ParseFunctions(die_offsets, include_inlines, sc_list);
- }
-}
-
-void SymbolFileDWARF::FindFunctions(
- const RegularExpression &regex,
- const DWARFMappedHash::MemoryTable &memory_table, bool include_inlines,
- SymbolContextList &sc_list) {
- DIEArray die_offsets;
- DWARFMappedHash::DIEInfoArray hash_data_array;
- if (memory_table.AppendAllDIEsThatMatchingRegex(regex, hash_data_array)) {
- DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
- ParseFunctions(die_offsets, include_inlines, sc_list);
- }
-}
-
-void SymbolFileDWARF::ParseFunctions(const DIEArray &die_offsets,
- bool include_inlines,
- SymbolContextList &sc_list) {
- const size_t num_matches = die_offsets.size();
- if (num_matches) {
- for (size_t i = 0; i < num_matches; ++i)
- ResolveFunction(die_offsets[i], include_inlines, sc_list);
- }
-}
-
bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx,
const DWARFDIE &die) {
// If we have no parent decl context to match this DIE matches, and if the
- // parent
- // decl context isn't valid, we aren't trying to look for any particular decl
- // context so any die matches.
+ // parent decl context isn't valid, we aren't trying to look for any
+ // particular decl context so any die matches.
if (decl_ctx == nullptr || !decl_ctx->IsValid())
return true;
@@ -2486,10 +2264,8 @@ SymbolFileDWARF::FindFunctions(const ConstString &name,
if (name.IsEmpty())
return 0;
- // Remember how many sc_list are in the list before we search in case
- // we are appending the results to a variable list.
-
- const char *name_cstr = name.GetCString();
+ // Remember how many sc_list are in the list before we search in case we are
+ // appending the results to a variable list.
const uint32_t original_size = sc_list.GetSize();
@@ -2497,228 +2273,17 @@ SymbolFileDWARF::FindFunctions(const ConstString &name,
if (info == NULL)
return 0;
- std::set<const DWARFDebugInfoEntry *> resolved_dies;
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
-
- DIEArray die_offsets;
-
- uint32_t num_matches = 0;
-
- if (name_type_mask & eFunctionNameTypeFull) {
- // If they asked for the full name, match what they typed. At some
- // point we may
- // want to canonicalize this (strip double spaces, etc. For now, we
- // just add all the
- // dies that we find by exact match.
- num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
- for (uint32_t i = 0; i < num_matches; i++) {
- const DIERef &die_ref = die_offsets[i];
- DWARFDIE die = info->GetDIE(die_ref);
- if (die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- continue; // The containing decl contexts don't match
-
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- } else {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')",
- die_ref.die_offset, name_cstr);
- }
- }
- }
-
- if (name_type_mask & eFunctionNameTypeSelector) {
- if (parent_decl_ctx && parent_decl_ctx->IsValid())
- return 0; // no selectors in namespaces
-
- num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
- // Now make sure these are actually ObjC methods. In this case we can
- // simply look up the name,
- // and if it is an ObjC method name, we're good.
+ llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
+ DIEArray offsets;
+ CompilerDeclContext empty_decl_ctx;
+ if (!parent_decl_ctx)
+ parent_decl_ctx = &empty_decl_ctx;
- for (uint32_t i = 0; i < num_matches; i++) {
- const DIERef &die_ref = die_offsets[i];
- DWARFDIE die = info->GetDIE(die_ref);
- if (die) {
- const char *die_name = die.GetName();
- if (ObjCLanguage::IsPossibleObjCMethodName(die_name)) {
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- }
- } else {
- GetObjectFile()->GetModule()->ReportError(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')",
- die_ref.die_offset, name_cstr);
- }
- }
- die_offsets.clear();
- }
-
- if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) ||
- name_type_mask & eFunctionNameTypeBase) {
- // The apple_names table stores just the "base name" of C++ methods in
- // the table. So we have to
- // extract the base name, look that up, and if there is any other
- // information in the name we were
- // passed in we have to post-filter based on that.
-
- // FIXME: Arrange the logic above so that we don't calculate the base
- // name twice:
- num_matches = m_apple_names_ap->FindByName(name_cstr, die_offsets);
-
- for (uint32_t i = 0; i < num_matches; i++) {
- const DIERef &die_ref = die_offsets[i];
- DWARFDIE die = info->GetDIE(die_ref);
- if (die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- continue; // The containing decl contexts don't match
-
- // If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() &&
- ResolveFunction(die, include_inlines, sc_list)) {
- bool keep_die = true;
- if ((name_type_mask &
- (eFunctionNameTypeBase | eFunctionNameTypeMethod)) !=
- (eFunctionNameTypeBase | eFunctionNameTypeMethod)) {
- // We are looking for either basenames or methods, so we need to
- // trim out the ones we won't want by looking at the type
- SymbolContext sc;
- if (sc_list.GetLastContext(sc)) {
- if (sc.block) {
- // We have an inlined function
- } else if (sc.function) {
- Type *type = sc.function->GetType();
-
- if (type) {
- CompilerDeclContext decl_ctx =
- GetDeclContextContainingUID(type->GetID());
- if (decl_ctx.IsStructUnionOrClass()) {
- if (name_type_mask & eFunctionNameTypeBase) {
- sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
- keep_die = false;
- }
- } else {
- if (name_type_mask & eFunctionNameTypeMethod) {
- sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1);
- keep_die = false;
- }
- }
- } else {
- GetObjectFile()->GetModule()->ReportWarning(
- "function at die offset 0x%8.8x had no function type",
- die_ref.die_offset);
- }
- }
- }
- }
- if (keep_die)
- resolved_dies.insert(die.GetDIE());
- }
- } else {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_names "
- "accelerator table had bad die 0x%8.8x for '%s')",
- die_ref.die_offset, name_cstr);
- }
- }
- die_offsets.clear();
- }
- }
- } else {
-
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
-
- if (name_type_mask & eFunctionNameTypeFull) {
- FindFunctions(name, m_function_fullname_index, include_inlines, sc_list);
-
- // FIXME Temporary workaround for global/anonymous namespace
- // functions debugging FreeBSD and Linux binaries.
- // If we didn't find any functions in the global namespace try
- // looking in the basename index but ignore any returned
- // functions that have a namespace but keep functions which
- // have an anonymous namespace
- // TODO: The arch in the object file isn't correct for MSVC
- // binaries on windows, we should find a way to make it
- // correct and handle those symbols as well.
- if (sc_list.GetSize() == original_size) {
- ArchSpec arch;
- if (!parent_decl_ctx && GetObjectFile()->GetArchitecture(arch) &&
- arch.GetTriple().isOSBinFormatELF()) {
- SymbolContextList temp_sc_list;
- FindFunctions(name, m_function_basename_index, include_inlines,
- temp_sc_list);
- SymbolContext sc;
- for (uint32_t i = 0; i < temp_sc_list.GetSize(); i++) {
- if (temp_sc_list.GetContextAtIndex(i, sc)) {
- ConstString mangled_name =
- sc.GetFunctionName(Mangled::ePreferMangled);
- ConstString demangled_name =
- sc.GetFunctionName(Mangled::ePreferDemangled);
- // Mangled names on Linux and FreeBSD are of the form:
- // _ZN18function_namespace13function_nameEv.
- if (strncmp(mangled_name.GetCString(), "_ZN", 3) ||
- !strncmp(demangled_name.GetCString(), "(anonymous namespace)",
- 21)) {
- sc_list.Append(sc);
- }
- }
- }
- }
- }
- }
- DIEArray die_offsets;
- if (name_type_mask & eFunctionNameTypeBase) {
- uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
- for (uint32_t i = 0; i < num_base; i++) {
- DWARFDIE die = info->GetDIE(die_offsets[i]);
- if (die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- continue; // The containing decl contexts don't match
-
- // If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- }
- }
- die_offsets.clear();
- }
-
- if (name_type_mask & eFunctionNameTypeMethod) {
- if (parent_decl_ctx && parent_decl_ctx->IsValid())
- return 0; // no methods in namespaces
-
- uint32_t num_base = m_function_method_index.Find(name, die_offsets);
- {
- for (uint32_t i = 0; i < num_base; i++) {
- DWARFDIE die = info->GetDIE(die_offsets[i]);
- if (die) {
- // If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die.GetDIE()) == resolved_dies.end()) {
- if (ResolveFunction(die, include_inlines, sc_list))
- resolved_dies.insert(die.GetDIE());
- }
- }
- }
- }
- die_offsets.clear();
- }
-
- if ((name_type_mask & eFunctionNameTypeSelector) &&
- (!parent_decl_ctx || !parent_decl_ctx->IsValid())) {
- FindFunctions(name, m_function_selector_index, include_inlines, sc_list);
- }
+ std::vector<DWARFDIE> dies;
+ m_index->GetFunctions(name, *info, *parent_decl_ctx, name_type_mask, dies);
+ for (const DWARFDIE &die: dies) {
+ if (resolved_dies.insert(die.GetDIE()).second)
+ ResolveFunction(die, include_inlines, sc_list);
}
// Return the number of variable that were appended to the list
@@ -2755,21 +2320,26 @@ uint32_t SymbolFileDWARF::FindFunctions(const RegularExpression &regex,
if (!append)
sc_list.Clear();
- // Remember how many sc_list are in the list before we search in case
- // we are appending the results to a variable list.
- uint32_t original_size = sc_list.GetSize();
+ DWARFDebugInfo *info = DebugInfo();
+ if (!info)
+ return 0;
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get())
- FindFunctions(regex, *m_apple_names_ap, include_inlines, sc_list);
- } else {
- // Index the DWARF if we haven't already
- if (!m_indexed)
- Index();
+ // Remember how many sc_list are in the list before we search in case we are
+ // appending the results to a variable list.
+ uint32_t original_size = sc_list.GetSize();
- FindFunctions(regex, m_function_basename_index, include_inlines, sc_list);
+ DIEArray offsets;
+ m_index->GetFunctions(regex, offsets);
- FindFunctions(regex, m_function_fullname_index, include_inlines, sc_list);
+ llvm::DenseSet<const DWARFDebugInfoEntry *> resolved_dies;
+ for (DIERef ref : offsets) {
+ DWARFDIE die = info->GetDIE(ref);
+ if (!die) {
+ m_index->ReportInvalidDIEOffset(ref.die_offset, regex.GetText());
+ continue;
+ }
+ if (resolved_dies.insert(die.GetDIE()).second)
+ ResolveFunction(die, include_inlines, sc_list);
}
// Return the number of variable that were appended to the list
@@ -2785,7 +2355,7 @@ void SymbolFileDWARF::GetMangledNamesForFunction(
num_comp_units = info->GetNumCompileUnits();
for (uint32_t i = 0; i < num_comp_units; i++) {
- DWARFCompileUnit *cu = info->GetCompileUnitAtIndex(i);
+ DWARFUnit *cu = info->GetCompileUnitAtIndex(i);
if (cu == nullptr)
continue;
@@ -2847,19 +2417,7 @@ uint32_t SymbolFileDWARF::FindTypes(
return 0;
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const char *name_cstr = name.GetCString();
- m_apple_types_ap->FindByName(name_cstr, die_offsets);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(name, die_offsets);
- }
-
+ m_index->GetTypes(name, die_offsets);
const size_t num_die_matches = die_offsets.size();
if (num_die_matches) {
@@ -2881,12 +2439,8 @@ uint32_t SymbolFileDWARF::FindTypes(
break;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
const uint32_t num_matches = types.GetSize() - initial_types_size;
@@ -2935,25 +2489,13 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
if (context.empty())
return 0;
- DIEArray die_offsets;
-
ConstString name = context.back().name;
if (!name)
return 0;
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const char *name_cstr = name.GetCString();
- m_apple_types_ap->FindByName(name_cstr, die_offsets);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(name, die_offsets);
- }
-
+ DIEArray die_offsets;
+ m_index->GetTypes(name, die_offsets);
const size_t num_die_matches = die_offsets.size();
if (num_die_matches) {
@@ -2976,12 +2518,8 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
++num_matches;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
return num_matches;
@@ -3008,21 +2546,7 @@ SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
DWARFDebugInfo *info = DebugInfo();
if (info) {
DIEArray die_offsets;
-
- // Index if we already haven't to make sure the compile units
- // get indexed and make their global DIE index list
- if (m_using_apple_tables) {
- if (m_apple_namespaces_ap.get()) {
- const char *name_cstr = name.GetCString();
- m_apple_namespaces_ap->FindByName(name_cstr, die_offsets);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_namespace_index.Find(name, die_offsets);
- }
-
+ m_index->GetNamespaces(name, die_offsets);
const size_t num_matches = die_offsets.size();
if (num_matches) {
for (size_t i = 0; i < num_matches; ++i) {
@@ -3040,13 +2564,8 @@ SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
break;
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified "
- "(.apple_namespaces accelerator table had bad die 0x%8.8x for "
- "'%s')\n",
- die_ref.die_offset, name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ name.GetStringRef());
}
}
}
@@ -3105,6 +2624,7 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) {
if (orig_die != die) {
switch (die.Tag()) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_union_type:
@@ -3159,16 +2679,14 @@ SymbolFileDWARF::GetObjCClassSymbol(const ConstString &objc_class_name) {
}
// Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If
-// they don't
-// then we can end up looking through all class types for a complete type and
-// never find
-// the full definition. We need to know if this attribute is supported, so we
-// determine
-// this here and cache th result. We also need to worry about the debug map
+// they don't then we can end up looking through all class types for a complete
+// type and never find the full definition. We need to know if this attribute
+// is supported, so we determine this here and cache th result. We also need to
+// worry about the debug map
// DWARF file
// if we are doing darwin DWARF in .o file debugging.
bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(
- DWARFCompileUnit *cu) {
+ DWARFUnit *cu) {
if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate) {
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type())
@@ -3177,7 +2695,7 @@ bool SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type(
DWARFDebugInfo *debug_info = DebugInfo();
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu != cu &&
dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type()) {
m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
@@ -3204,19 +2722,7 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
return type_sp;
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const char *name_cstr = type_name.GetCString();
- m_apple_types_ap->FindCompleteObjCClassByName(name_cstr, die_offsets,
- must_be_implementation);
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(type_name, die_offsets);
- }
+ m_index->GetCompleteObjCClass(type_name, must_be_implementation, die_offsets);
const size_t num_matches = die_offsets.size();
@@ -3228,7 +2734,8 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
if (type_die) {
bool try_resolving_type = false;
- // Don't try and resolve the DIE we are looking for with the DIE itself!
+ // Don't try and resolve the DIE we are looking for with the DIE
+ // itself!
if (type_die != die) {
switch (type_die.Tag()) {
case DW_TAG_class_type:
@@ -3264,12 +2771,8 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
}
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, type_name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ type_name.GetStringRef());
}
}
}
@@ -3277,16 +2780,15 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE(
}
//----------------------------------------------------------------------
-// This function helps to ensure that the declaration contexts match for
-// two different DIEs. Often times debug information will refer to a
-// forward declaration of a type (the equivalent of "struct my_struct;".
-// There will often be a declaration of that type elsewhere that has the
-// full definition. When we go looking for the full type "my_struct", we
-// will find one or more matches in the accelerator tables and we will
-// then need to make sure the type was in the same declaration context
-// as the original DIE. This function can efficiently compare two DIEs
-// and will return true when the declaration context matches, and false
-// when they don't.
+// This function helps to ensure that the declaration contexts match for two
+// different DIEs. Often times debug information will refer to a forward
+// declaration of a type (the equivalent of "struct my_struct;". There will
+// often be a declaration of that type elsewhere that has the full definition.
+// When we go looking for the full type "my_struct", we will find one or more
+// matches in the accelerator tables and we will then need to make sure the
+// type was in the same declaration context as the original DIE. This function
+// can efficiently compare two DIEs and will return true when the declaration
+// context matches, and false when they don't.
//----------------------------------------------------------------------
bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
const DWARFDIE &die2) {
@@ -3295,32 +2797,31 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
DWARFDIECollection decl_ctx_1;
DWARFDIECollection decl_ctx_2;
- // The declaration DIE stack is a stack of the declaration context
- // DIEs all the way back to the compile unit. If a type "T" is
- // declared inside a class "B", and class "B" is declared inside
- // a class "A" and class "A" is in a namespace "lldb", and the
- // namespace is in a compile unit, there will be a stack of DIEs:
+ // The declaration DIE stack is a stack of the declaration context DIEs all
+ // the way back to the compile unit. If a type "T" is declared inside a class
+ // "B", and class "B" is declared inside a class "A" and class "A" is in a
+ // namespace "lldb", and the namespace is in a compile unit, there will be a
+ // stack of DIEs:
//
// [0] DW_TAG_class_type for "B"
// [1] DW_TAG_class_type for "A"
// [2] DW_TAG_namespace for "lldb"
- // [3] DW_TAG_compile_unit for the source file.
+ // [3] DW_TAG_compile_unit or DW_TAG_partial_unit for the source file.
//
- // We grab both contexts and make sure that everything matches
- // all the way back to the compiler unit.
+ // We grab both contexts and make sure that everything matches all the way
+ // back to the compiler unit.
// First lets grab the decl contexts for both DIEs
die1.GetDeclContextDIEs(decl_ctx_1);
die2.GetDeclContextDIEs(decl_ctx_2);
- // Make sure the context arrays have the same size, otherwise
- // we are done
+ // Make sure the context arrays have the same size, otherwise we are done
const size_t count1 = decl_ctx_1.Size();
const size_t count2 = decl_ctx_2.Size();
if (count1 != count2)
return false;
- // Make sure the DW_TAG values match all the way back up the
- // compile unit. If they don't, then we are done.
+ // Make sure the DW_TAG values match all the way back up the compile unit. If
+ // they don't, then we are done.
DWARFDIE decl_ctx_die1;
DWARFDIE decl_ctx_die2;
size_t i;
@@ -3333,25 +2834,28 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
#if defined LLDB_CONFIGURATION_DEBUG
// Make sure the top item in the decl context die array is always
- // DW_TAG_compile_unit. If it isn't then something went wrong in
- // the DWARFDIE::GetDeclContextDIEs() function...
- assert(decl_ctx_1.GetDIEAtIndex(count1 - 1).Tag() == DW_TAG_compile_unit);
+ // DW_TAG_compile_unit or DW_TAG_partial_unit. If it isn't then
+ // something went wrong in the DWARFDIE::GetDeclContextDIEs()
+ // function.
+ dw_tag_t cu_tag = decl_ctx_1.GetDIEAtIndex(count1 - 1).Tag();
+ UNUSED_IF_ASSERT_DISABLED(cu_tag);
+ assert(cu_tag == DW_TAG_compile_unit || cu_tag == DW_TAG_partial_unit);
#endif
- // Always skip the compile unit when comparing by only iterating up to
- // "count - 1". Here we compare the names as we go.
+ // Always skip the compile unit when comparing by only iterating up to "count
+ // - 1". Here we compare the names as we go.
for (i = 0; i < count1 - 1; i++) {
decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex(i);
decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex(i);
const char *name1 = decl_ctx_die1.GetName();
const char *name2 = decl_ctx_die2.GetName();
- // If the string was from a DW_FORM_strp, then the pointer will often
- // be the same!
+ // If the string was from a DW_FORM_strp, then the pointer will often be
+ // the same!
if (name1 == name2)
continue;
- // Name pointers are not equal, so only compare the strings
- // if both are not NULL.
+ // Name pointers are not equal, so only compare the strings if both are not
+ // NULL.
if (name1 && name2) {
// If the strings don't compare, we are done...
if (strcmp(name1, name2) != 0)
@@ -3361,8 +2865,8 @@ bool SymbolFileDWARF::DIEDeclContextsMatch(const DWARFDIE &die1,
return false;
}
}
- // We made it through all of the checks and the declaration contexts
- // are equal.
+ // We made it through all of the checks and the declaration contexts are
+ // equal.
return true;
}
@@ -3387,47 +2891,12 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
}
DIEArray die_offsets;
-
- if (m_using_apple_tables) {
- if (m_apple_types_ap.get()) {
- const bool has_tag =
- m_apple_types_ap->GetHeader().header_data.ContainsAtom(
- DWARFMappedHash::eAtomTypeTag);
- const bool has_qualified_name_hash =
- m_apple_types_ap->GetHeader().header_data.ContainsAtom(
- DWARFMappedHash::eAtomTypeQualNameHash);
- if (has_tag && has_qualified_name_hash) {
- const char *qualified_name = dwarf_decl_ctx.GetQualifiedName();
- const uint32_t qualified_name_hash =
- MappedHash::HashStringUsingDJB(qualified_name);
- if (log)
- GetObjectFile()->GetModule()->LogMessage(
- log, "FindByNameAndTagAndQualifiedNameHash()");
- m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash(
- type_name.GetCString(), tag, qualified_name_hash, die_offsets);
- } else if (has_tag) {
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log,
- "FindByNameAndTag()");
- m_apple_types_ap->FindByNameAndTag(type_name.GetCString(), tag,
- die_offsets);
- } else {
- m_apple_types_ap->FindByName(type_name.GetCString(), die_offsets);
- }
- }
- } else {
- if (!m_indexed)
- Index();
-
- m_type_index.Find(type_name, die_offsets);
- }
-
+ m_index->GetTypes(dwarf_decl_ctx, die_offsets);
const size_t num_matches = die_offsets.size();
- // Get the type system that we are looking to find a type for. We will use
- // this
- // to ensure any matches we find are in a language that this type system
- // supports
+ // Get the type system that we are looking to find a type for. We will
+ // use this to ensure any matches we find are in a language that this
+ // type system supports
const LanguageType language = dwarf_decl_ctx.GetLanguage();
TypeSystem *type_system = (language == eLanguageTypeUnknown)
? nullptr
@@ -3440,10 +2909,8 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
if (type_die) {
// Make sure type_die's langauge matches the type system we are
- // looking for.
- // We don't want to find a "Foo" type from Java if we are looking
- // for a "Foo"
- // type for C, C++, ObjC, or ObjC++.
+ // looking for. We don't want to find a "Foo" type from Java if we
+ // are looking for a "Foo" type for C, C++, ObjC, or ObjC++.
if (type_system &&
!type_system->SupportsLanguage(type_die.GetLanguage()))
continue;
@@ -3457,24 +2924,23 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
// The tags match, lets try resolving this type
try_resolving_type = true;
} else {
- // The tags don't match, but we need to watch our for a
- // forward declaration for a struct and ("struct foo")
- // ends up being a class ("class foo { ... };") or
- // vice versa.
+ // The tags don't match, but we need to watch our for a forward
+ // declaration for a struct and ("struct foo") ends up being a
+ // class ("class foo { ... };") or vice versa.
switch (type_tag) {
case DW_TAG_class_type:
- // We had a "class foo", see if we ended up with a "struct foo {
- // ... };"
+ // We had a "class foo", see if we ended up with a "struct foo
+ // { ... };"
try_resolving_type = (tag == DW_TAG_structure_type);
break;
case DW_TAG_structure_type:
- // We had a "struct foo", see if we ended up with a "class foo {
- // ... };"
+ // We had a "struct foo", see if we ended up with a "class foo
+ // { ... };"
try_resolving_type = (tag == DW_TAG_class_type);
break;
default:
- // Tags don't match, don't event try to resolve
- // using this type whose name matches....
+ // Tags don't match, don't event try to resolve using this type
+ // whose name matches....
break;
}
}
@@ -3515,12 +2981,8 @@ TypeSP SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(
}
}
} else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified (.apple_types "
- "accelerator table had bad die 0x%8.8x for '%s')\n",
- die_ref.die_offset, type_name.GetCString());
- }
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset,
+ type_name.GetStringRef());
}
}
}
@@ -3606,7 +3068,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc,
size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc) {
assert(sc.comp_unit && sc.function);
size_t functions_added = 0;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
const dw_offset_t function_die_offset = sc.function->GetID();
DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset);
@@ -3623,7 +3085,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc) {
// At least a compile unit must be valid
assert(sc.comp_unit);
size_t types_added = 0;
- DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
if (sc.function) {
dw_offset_t function_die_offset = sc.function->GetID();
@@ -3662,7 +3124,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
return num_variables;
}
} else if (sc.comp_unit) {
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());
+ DWARFUnit *dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());
if (dwarf_cu == NULL)
return 0;
@@ -3675,25 +3137,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
sc.comp_unit->SetVariableList(variables);
DIEArray die_offsets;
- if (m_using_apple_tables) {
- if (m_apple_names_ap.get()) {
- DWARFMappedHash::DIEInfoArray hash_data_array;
- if (m_apple_names_ap->AppendAllDIEsInRange(
- dwarf_cu->GetOffset(), dwarf_cu->GetNextCompileUnitOffset(),
- hash_data_array)) {
- DWARFMappedHash::ExtractDIEArray(hash_data_array, die_offsets);
- }
- }
- } else {
- // Index if we already haven't to make sure the compile units
- // get indexed and make their global DIE index list
- if (!m_indexed)
- Index();
-
- m_global_index.FindAllEntriesForCompileUnit(dwarf_cu->GetOffset(),
- die_offsets);
- }
-
+ m_index->GetGlobalVariables(*dwarf_cu, die_offsets);
const size_t num_matches = die_offsets.size();
if (num_matches) {
for (size_t i = 0; i < num_matches; ++i) {
@@ -3706,14 +3150,8 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
variables->AddVariableIfUnique(var_sp);
++vars_added;
}
- } else {
- if (m_using_apple_tables) {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected(
- "the DWARF debug information has been modified "
- "(.apple_names accelerator table had bad die 0x%8.8x)\n",
- die_ref.die_offset);
- }
- }
+ } else
+ m_index->ReportInvalidDIEOffset(die_ref.die_offset, "");
}
}
}
@@ -3796,7 +3234,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
location_is_const_value_data = true;
// The constant value will be either a block, a data value or a
// string.
- const DWARFDataExtractor &debug_info_data = get_debug_info_data();
+ auto debug_info_data = die.GetData();
if (DWARFFormValue::IsBlockForm(form_value.Form())) {
// Retrieve the value as a block expression.
uint32_t block_offset =
@@ -3853,13 +3291,12 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
location_is_const_value_data = false;
has_explicit_location = true;
if (DWARFFormValue::IsBlockForm(form_value.Form())) {
- const DWARFDataExtractor &debug_info_data = get_debug_info_data();
+ auto data = die.GetData();
uint32_t block_offset =
- form_value.BlockData() - debug_info_data.GetDataStart();
+ form_value.BlockData() - data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- location.CopyOpcodeData(module, get_debug_info_data(),
- block_offset, block_length);
+ location.CopyOpcodeData(module, data, block_offset, block_length);
} else {
const DWARFDataExtractor &debug_loc_data = get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
@@ -3902,10 +3339,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
// TODO: Handle the case when DW_AT_start_scope have form
// constant. The
// dwarf spec is a bit ambiguous about what is the expected
- // behavior in
- // case the enclosing block have a non coninious address range and
- // the
- // DW_AT_start_scope entry have a form constant.
+ // behavior in case the enclosing block have a non coninious
+ // address range and the DW_AT_start_scope entry have a form
+ // constant.
GetObjectFile()->GetModule()->ReportWarning(
"0x%8.8" PRIx64
": DW_AT_start_scope has unsupported form type (0x%x)\n",
@@ -3937,7 +3373,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
const dw_tag_t parent_tag = die.GetParent().Tag();
bool is_static_member =
- parent_tag == DW_TAG_compile_unit &&
+ (parent_tag == DW_TAG_compile_unit ||
+ parent_tag == DW_TAG_partial_unit) &&
(parent_context_die.Tag() == DW_TAG_class_type ||
parent_context_die.Tag() == DW_TAG_structure_type);
@@ -3949,17 +3386,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
bool has_explicit_mangled = mangled != nullptr;
if (!mangled) {
// LLDB relies on the mangled name (DW_TAG_linkage_name or
- // DW_AT_MIPS_linkage_name) to
- // generate fully qualified names of global variables with commands like
- // "frame var j".
- // For example, if j were an int variable holding a value 4 and declared
- // in a namespace
- // B which in turn is contained in a namespace A, the command "frame var
- // j" returns
- // "(int) A::B::j = 4". If the compiler does not emit a linkage name, we
- // should be able
- // to generate a fully qualified name from the declaration context.
- if (parent_tag == DW_TAG_compile_unit &&
+ // DW_AT_MIPS_linkage_name) to generate fully qualified names
+ // of global variables with commands like "frame var j". For
+ // example, if j were an int variable holding a value 4 and
+ // declared in a namespace B which in turn is contained in a
+ // namespace A, the command "frame var j" returns
+ // "(int) A::B::j = 4".
+ // If the compiler does not emit a linkage name, we should be
+ // able to generate a fully qualified name from the
+ // declaration context.
+ if ((parent_tag == DW_TAG_compile_unit ||
+ parent_tag == DW_TAG_partial_unit) &&
Language::LanguageIsCPlusPlus(die.GetLanguage())) {
DWARFDeclContext decl_ctx;
@@ -4007,24 +3444,21 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
scope = eValueTypeVariableStatic;
if (debug_map_symfile) {
- // When leaving the DWARF in the .o files on darwin,
- // when we have a global variable that wasn't initialized,
- // the .o file might not have allocated a virtual
- // address for the global variable. In this case it will
- // have created a symbol for the global variable
- // that is undefined/data and external and the value will
- // be the byte size of the variable. When we do the
- // address map in SymbolFileDWARFDebugMap we rely on
- // having an address, we need to do some magic here
- // so we can get the correct address for our global
- // variable. The address for all of these entries
- // will be zero, and there will be an undefined symbol
- // in this object file, and the executable will have
- // a matching symbol with a good address. So here we
- // dig up the correct address and replace it in the
- // location for the variable, and set the variable's
- // symbol context scope to be that of the main executable
- // so the file address will resolve correctly.
+ // When leaving the DWARF in the .o files on darwin, when we have a
+ // global variable that wasn't initialized, the .o file might not
+ // have allocated a virtual address for the global variable. In
+ // this case it will have created a symbol for the global variable
+ // that is undefined/data and external and the value will be the
+ // byte size of the variable. When we do the address map in
+ // SymbolFileDWARFDebugMap we rely on having an address, we need to
+ // do some magic here so we can get the correct address for our
+ // global variable. The address for all of these entries will be
+ // zero, and there will be an undefined symbol in this object file,
+ // and the executable will have a matching symbol with a good
+ // address. So here we dig up the correct address and replace it in
+ // the location for the variable, and set the variable's symbol
+ // context scope to be that of the main executable so the file
+ // address will resolve correctly.
bool linked_oso_file_addr = false;
if (is_external && location_DW_OP_addr == 0) {
// we have a possible uninitialized extern global
@@ -4056,8 +3490,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
if (!linked_oso_file_addr) {
// The DW_OP_addr is not zero, but it contains a .o file address
- // which
- // needs to be linked up correctly.
+ // which needs to be linked up correctly.
const lldb::addr_t exe_file_addr =
debug_map_symfile->LinkOSOFileAddress(this,
location_DW_OP_addr);
@@ -4127,16 +3560,16 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
var_sp->SetLocationIsConstantValueData(location_is_const_value_data);
} else {
- // Not ready to parse this variable yet. It might be a global
- // or static variable that is in a function scope and the function
- // in the symbol context wasn't filled in yet
+ // Not ready to parse this variable yet. It might be a global or static
+ // variable that is in a function scope and the function in the symbol
+ // context wasn't filled in yet
return var_sp;
}
}
- // Cache var_sp even if NULL (the variable was just a specification or
- // was missing vital information to be able to be displayed in the debugger
- // (missing location due to optimization, etc)) so we don't re-parse
- // this DIE over and over later...
+ // Cache var_sp even if NULL (the variable was just a specification or was
+ // missing vital information to be able to be displayed in the debugger
+ // (missing location due to optimization, etc)) so we don't re-parse this
+ // DIE over and over later...
GetDIEToVariable()[die.GetDIE()] = var_sp;
if (spec_die)
GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
@@ -4217,11 +3650,11 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc,
dw_tag_t parent_tag = sc_parent_die.Tag();
switch (parent_tag) {
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
if (sc.comp_unit != NULL) {
variable_list_sp = sc.comp_unit->GetVariableList(false);
if (variable_list_sp.get() == NULL) {
variable_list_sp.reset(new VariableList());
- sc.comp_unit->SetVariableList(variable_list_sp);
}
} else {
GetObjectFile()->GetModule()->ReportError(
@@ -4243,8 +3676,8 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc,
Block *block = sc.function->GetBlock(true).FindBlockByID(
sc_parent_die.GetID());
if (block == NULL) {
- // This must be a specification or abstract origin with
- // a concrete block counterpart in the current function. We need
+ // This must be a specification or abstract origin with a
+ // concrete block counterpart in the current function. We need
// to find the concrete block so we can correctly add the
// variable to it
const DWARFDIE concrete_block_die =
@@ -4310,30 +3743,7 @@ ConstString SymbolFileDWARF::GetPluginName() { return GetPluginNameStatic(); }
uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; }
-void SymbolFileDWARF::DumpIndexes() {
- StreamFile s(stdout, false);
-
- s.Printf(
- "DWARF index for (%s) '%s':",
- GetObjectFile()->GetModule()->GetArchitecture().GetArchitectureName(),
- GetObjectFile()->GetFileSpec().GetPath().c_str());
- s.Printf("\nFunction basenames:\n");
- m_function_basename_index.Dump(&s);
- s.Printf("\nFunction fullnames:\n");
- m_function_fullname_index.Dump(&s);
- s.Printf("\nFunction methods:\n");
- m_function_method_index.Dump(&s);
- s.Printf("\nFunction selectors:\n");
- m_function_selector_index.Dump(&s);
- s.Printf("\nObjective C class selectors:\n");
- m_objc_class_selectors_index.Dump(&s);
- s.Printf("\nGlobals and statics:\n");
- m_global_index.Dump(&s);
- s.Printf("\nTypes:\n");
- m_type_index.Dump(&s);
- s.Printf("\nNamespaces:\n");
- m_namespace_index.Dump(&s);
-}
+void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); }
SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) {
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 6902dc0333d2..a5f2ac8f3e7d 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -38,8 +38,7 @@
// Project includes
#include "DWARFDataExtractor.h"
#include "DWARFDefines.h"
-#include "HashedNameToDIE.h"
-#include "NameToDIE.h"
+#include "DWARFIndex.h"
#include "UniqueDWARFASTType.h"
//----------------------------------------------------------------------
@@ -54,7 +53,6 @@ class DWARFDebugAranges;
class DWARFDebugInfo;
class DWARFDebugInfoEntry;
class DWARFDebugLine;
-class DWARFDebugPubnames;
class DWARFDebugRanges;
class DWARFDeclContext;
class DWARFDIECollection;
@@ -72,7 +70,7 @@ public:
friend class SymbolFileDWARFDwo;
friend class DebugMapModule;
friend struct DIERef;
- friend class DWARFCompileUnit;
+ friend class DWARFUnit;
friend class DWARFDIE;
friend class DWARFASTParserClang;
friend class DWARFASTParserGo;
@@ -181,11 +179,11 @@ public:
uint32_t
FindGlobalVariables(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t
@@ -247,10 +245,12 @@ public:
const lldb_private::DWARFDataExtractor &get_debug_ranges_data();
const lldb_private::DWARFDataExtractor &get_debug_str_data();
const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
+ const lldb_private::DWARFDataExtractor &get_debug_types_data();
const lldb_private::DWARFDataExtractor &get_apple_names_data();
const lldb_private::DWARFDataExtractor &get_apple_types_data();
const lldb_private::DWARFDataExtractor &get_apple_namespaces_data();
const lldb_private::DWARFDataExtractor &get_apple_objc_data();
+ const lldb_private::DWARFDataExtractor &get_gnu_debugaltlink();
DWARFDebugAbbrev *DebugAbbrev();
@@ -273,19 +273,19 @@ public:
HasForwardDeclForClangType(const lldb_private::CompilerType &compiler_type);
lldb_private::CompileUnit *
- GetCompUnitForDWARFCompUnit(DWARFCompileUnit *dwarf_cu,
+ GetCompUnitForDWARFCompUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx = UINT32_MAX);
virtual size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name,
DIEArray &method_die_offsets);
- bool Supports_DW_AT_APPLE_objc_complete_type(DWARFCompileUnit *cu);
+ bool Supports_DW_AT_APPLE_objc_complete_type(DWARFUnit *cu);
lldb_private::DebugMacrosSP ParseDebugMacros(lldb::offset_t *offset);
static DWARFDIE GetParentSymbolContextDIE(const DWARFDIE &die);
- virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+ virtual lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx);
virtual lldb_private::DWARFExpression::LocationListFormat
@@ -293,16 +293,30 @@ public:
lldb::ModuleSP GetDWOModule(lldb_private::ConstString name);
+ typedef std::map<lldb_private::ConstString, lldb::ModuleSP>
+ ExternalTypeModuleMap;
+
+ /// Return the list of Clang modules imported by this SymbolFile.
+ const ExternalTypeModuleMap& getExternalTypeModules() const {
+ return m_external_type_modules;
+ }
+
virtual DWARFDIE GetDIE(const DIERef &die_ref);
virtual std::unique_ptr<SymbolFileDWARFDwo>
- GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu,
+ GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
const DWARFDebugInfoEntry &cu_die);
// For regular SymbolFileDWARF instances the method returns nullptr,
// for the instances of the subclass SymbolFileDWARFDwo
// the method returns a pointer to the base compile unit.
- virtual DWARFCompileUnit *GetBaseCompileUnit();
+ virtual DWARFUnit *GetBaseCompileUnit();
+
+ static bool
+ DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ const DWARFDIE &die);
+
+ void Dump(lldb_private::Stream &s) override;
protected:
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
@@ -331,14 +345,10 @@ protected:
bool DeclContextMatchesThisSymbolFile(
const lldb_private::CompilerDeclContext *decl_ctx);
- bool
- DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
- const DWARFDIE &die);
-
- virtual DWARFCompileUnit *
+ virtual DWARFUnit *
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit);
- DWARFCompileUnit *GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit *prev_cu);
+ DWARFUnit *GetNextUnparsedDWARFCompileUnit(DWARFUnit *prev_cu);
bool GetFunction(const DWARFDIE &die, lldb_private::SymbolContext &sc);
@@ -375,25 +385,9 @@ protected:
bool ClassOrStructIsVirtual(const DWARFDIE &die);
// Given a die_offset, figure out the symbol context representing that die.
- bool ResolveFunction(const DIERef &die_ref, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
bool ResolveFunction(const DWARFDIE &die, bool include_inlines,
lldb_private::SymbolContextList &sc_list);
- void FindFunctions(const lldb_private::ConstString &name,
- const NameToDIE &name_to_die, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
- void FindFunctions(const lldb_private::RegularExpression &regex,
- const NameToDIE &name_to_die, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
- void FindFunctions(const lldb_private::RegularExpression &regex,
- const DWARFMappedHash::MemoryTable &memory_table,
- bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
virtual lldb::TypeSP
FindDefinitionTypeForDWARFDeclContext(const DWARFDeclContext &die_decl_ctx);
@@ -404,16 +398,9 @@ protected:
lldb_private::Symbol *
GetObjCClassSymbol(const lldb_private::ConstString &objc_class_name);
- void ParseFunctions(const DIEArray &die_offsets, bool include_inlines,
- lldb_private::SymbolContextList &sc_list);
-
lldb::TypeSP GetTypeForDIE(const DWARFDIE &die,
bool resolve_function_context = false);
- void Index();
-
- void DumpIndexes();
-
void SetDebugMapModule(const lldb::ModuleSP &module_sp) {
m_debug_map_module_wp = module_sp;
}
@@ -439,9 +426,6 @@ protected:
typedef std::set<lldb_private::Type *> TypeSet;
- typedef std::map<lldb_private::ConstString, lldb::ModuleSP>
- ExternalTypeModuleMap;
-
void GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset,
dw_offset_t max_die_offset, uint32_t type_mask,
TypeSet &type_set);
@@ -487,10 +471,12 @@ protected:
DWARFDataSegment m_data_debug_ranges;
DWARFDataSegment m_data_debug_str;
DWARFDataSegment m_data_debug_str_offsets;
+ DWARFDataSegment m_data_debug_types;
DWARFDataSegment m_data_apple_names;
DWARFDataSegment m_data_apple_types;
DWARFDataSegment m_data_apple_namespaces;
DWARFDataSegment m_data_apple_objc;
+ DWARFDataSegment m_data_gnu_debugaltlink;
// The unique pointer items below are generated on demand if and when someone
// accesses
@@ -498,10 +484,6 @@ protected:
std::unique_ptr<DWARFDebugAbbrev> m_abbr;
std::unique_ptr<DWARFDebugInfo> m_info;
std::unique_ptr<DWARFDebugLine> m_line;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_names_ap;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_ap;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
- std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP>
@@ -509,17 +491,8 @@ protected:
DebugMacrosMap m_debug_macros_map;
ExternalTypeModuleMap m_external_type_modules;
- NameToDIE m_function_basename_index; // All concrete functions
- NameToDIE m_function_fullname_index; // All concrete functions
- NameToDIE m_function_method_index; // All inlined functions
- NameToDIE
- m_function_selector_index; // All method names for functions of classes
- NameToDIE m_objc_class_selectors_index; // Given a class name, find all
- // selectors for the class
- NameToDIE m_global_index; // Global and static variables
- NameToDIE m_type_index; // All type DIE offsets
- NameToDIE m_namespace_index; // All type DIE offsets
- bool m_indexed : 1, m_using_apple_tables : 1, m_fetched_external_modules : 1;
+ std::unique_ptr<lldb_private::DWARFIndex> m_index;
+ bool m_fetched_external_modules : 1;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
typedef std::shared_ptr<std::set<DIERef>> DIERefSetSP;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index eabff86a5428..39c70d146524 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -44,10 +44,8 @@ using namespace lldb;
using namespace lldb_private;
// Subclass lldb_private::Module so we can intercept the
-// "Module::GetObjectFile()"
-// (so we can fixup the object file sections) and also for
-// "Module::GetSymbolVendor()"
-// (so we can fixup the symbol file id.
+// "Module::GetObjectFile()" (so we can fixup the object file sections) and
+// also for "Module::GetSymbolVendor()" (so we can fixup the symbol file id.
const SymbolFileDWARFDebugMap::FileRangeMap &
SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
@@ -84,8 +82,8 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
/// const uint32_t fun_resolve_flags = SymbolContext::Module |
/// eSymbolContextCompUnit | eSymbolContextFunction;
// SectionList *oso_sections = oso_objfile->Sections();
- // Now we need to make sections that map from zero based object
- // file addresses to where things ended up in the main executable.
+ // Now we need to make sections that map from zero based object file
+ // addresses to where things ended up in the main executable.
assert(comp_unit_info->first_symbol_index != UINT32_MAX);
// End index is one past the last valid symbol index
@@ -104,9 +102,9 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
break;
case eSymbolTypeCode: {
- // For each N_FUN, or function that we run into in the debug map
- // we make a new section that we add to the sections found in the
- // .o file. This new section has the file address set to what the
+ // For each N_FUN, or function that we run into in the debug map we
+ // make a new section that we add to the sections found in the .o
+ // file. This new section has the file address set to what the
// addresses are in the .o file, and the load address is adjusted
// to match where it ended up in the final executable! We do this
// before we parse any dwarf info so that when it goes get parsed
@@ -129,21 +127,21 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
} break;
case eSymbolTypeData: {
- // For each N_GSYM we remap the address for the global by making
- // a new section that we add to the sections found in the .o file.
- // This new section has the file address set to what the
- // addresses are in the .o file, and the load address is adjusted
- // to match where it ended up in the final executable! We do this
- // before we parse any dwarf info so that when it goes get parsed
- // all section/offset addresses that get registered will resolve
+ // For each N_GSYM we remap the address for the global by making a
+ // new section that we add to the sections found in the .o file.
+ // This new section has the file address set to what the addresses
+ // are in the .o file, and the load address is adjusted to match
+ // where it ended up in the final executable! We do this before we
+ // parse any dwarf info so that when it goes get parsed all
+ // section/offset addresses that get registered will resolve
// correctly to the new addresses in the main executable. We
// initially set the section size to be 1 byte, but will need to
// fix up these addresses further after all globals have been
// parsed to span the gaps, or we can find the global variable
// sizes from the DWARF info as we are parsing.
- // Next we find the non-stab entry that corresponds to the N_GSYM in
- // the .o file
+ // Next we find the non-stab entry that corresponds to the N_GSYM
+ // in the .o file
Symbol *oso_gsym_symbol =
oso_symtab->FindFirstSymbolWithNameAndType(
exe_symbol->GetMangled().GetName(lldb::eLanguageTypeUnknown,
@@ -198,9 +196,9 @@ public:
SymbolVendor *symbol_vendor =
Module::GetSymbolVendor(can_create, feedback_strm);
if (symbol_vendor) {
- // Set a pointer to this class to set our OSO DWARF file know
- // that the DWARF is being used along with a debug map and that
- // it will have the remapped sections that we do below.
+ // Set a pointer to this class to set our OSO DWARF file know that
+ // the DWARF is being used along with a debug map and that it will
+ // have the remapped sections that we do below.
SymbolFileDWARF *oso_symfile =
SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(
symbol_vendor->GetSymbolFile());
@@ -292,8 +290,8 @@ void SymbolFileDWARFDebugMap::InitOSO() {
// In order to get the abilities of this plug-in, we look at the list of
// N_OSO entries (object files) from the symbol table and make sure that
- // these files exist and also contain valid DWARF. If we get any of that
- // then we return the abilities of the first N_OSO's DWARF.
+ // these files exist and also contain valid DWARF. If we get any of that then
+ // we return the abilities of the first N_OSO's DWARF.
Symtab *symtab = m_obj_file->GetSymtab();
if (symtab) {
@@ -303,10 +301,10 @@ void SymbolFileDWARFDebugMap::InitOSO() {
// When a mach-o symbol is encoded, the n_type field is encoded in bits
// 23:16, and the n_desc field is encoded in bits 15:0.
//
- // To find all N_OSO entries that are part of the DWARF + debug map
- // we find only object file symbols with the flags value as follows:
- // bits 23:16 == 0x66 (N_OSO)
- // bits 15: 0 == 0x0001 (specifies this is a debug map object file)
+ // To find all N_OSO entries that are part of the DWARF + debug map we find
+ // only object file symbols with the flags value as follows: bits 23:16 ==
+ // 0x66 (N_OSO) bits 15: 0 == 0x0001 (specifies this is a debug map object
+ // file)
const uint32_t k_oso_symbol_flags_value = 0x660001u;
const uint32_t oso_index_count =
@@ -353,7 +351,7 @@ void SymbolFileDWARFDebugMap::InitOSO() {
so_symbol->GetType() == eSymbolTypeSourceFile &&
oso_symbol->GetType() == eSymbolTypeObjectFile) {
m_compile_unit_infos[i].so_file.SetFile(
- so_symbol->GetName().AsCString(), false);
+ so_symbol->GetName().AsCString(), false, FileSpec::Style::native);
m_compile_unit_infos[i].oso_path = oso_symbol->GetName();
m_compile_unit_infos[i].oso_mod_time =
llvm::sys::toTimePoint(oso_symbol->GetIntegerValue(0));
@@ -413,13 +411,15 @@ Module *SymbolFileDWARFDebugMap::GetModuleByOSOIndex(uint32_t oso_idx) {
Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
CompileUnitInfo *comp_unit_info) {
if (!comp_unit_info->oso_sp) {
- auto pos = m_oso_map.find(comp_unit_info->oso_path);
+ auto pos = m_oso_map.find(
+ {comp_unit_info->oso_path, comp_unit_info->oso_mod_time});
if (pos != m_oso_map.end()) {
comp_unit_info->oso_sp = pos->second;
} else {
ObjectFile *obj_file = GetObjectFile();
comp_unit_info->oso_sp.reset(new OSOInfo());
- m_oso_map[comp_unit_info->oso_path] = comp_unit_info->oso_sp;
+ m_oso_map[{comp_unit_info->oso_path, comp_unit_info->oso_mod_time}] =
+ comp_unit_info->oso_sp;
const char *oso_path = comp_unit_info->oso_path.GetCString();
FileSpec oso_file(oso_path, false);
ConstString oso_object;
@@ -443,16 +443,15 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
return NULL;
}
}
- // Always create a new module for .o files. Why? Because we
- // use the debug map, to add new sections to each .o file and
- // even though a .o file might not have changed, the sections
- // that get added to the .o file can change.
+ // Always create a new module for .o files. Why? Because we use the debug
+ // map, to add new sections to each .o file and even though a .o file
+ // might not have changed, the sections that get added to the .o file can
+ // change.
ArchSpec oso_arch;
// Only adopt the architecture from the module (not the vendor or OS)
- // since .o files for "i386-apple-ios" will historically show up as
- // "i386-apple-macosx"
- // due to the lack of a LC_VERSION_MIN_MACOSX or LC_VERSION_MIN_IPHONEOS
- // load command...
+ // since .o files for "i386-apple-ios" will historically show up as "i386
+ // -apple-macosx" due to the lack of a LC_VERSION_MIN_MACOSX or
+ // LC_VERSION_MIN_IPHONEOS load command...
oso_arch.SetTriple(m_obj_file->GetModule()
->GetArchitecture()
.GetTriple()
@@ -546,8 +545,8 @@ SymbolFileDWARF *SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo(
uint32_t SymbolFileDWARFDebugMap::CalculateAbilities() {
// In order to get the abilities of this plug-in, we look at the list of
// N_OSO entries (object files) from the symbol table and make sure that
- // these files exist and also contain valid DWARF. If we get any of that
- // then we return the abilities of the first N_OSO's DWARF.
+ // these files exist and also contain valid DWARF. If we get any of that then
+ // we return the abilities of the first N_OSO's DWARF.
const uint32_t oso_index_count = GetNumCompileUnits();
if (oso_index_count > 0) {
@@ -576,9 +575,8 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) {
if (oso_module) {
FileSpec so_file_spec;
if (GetFileSpecForSO(cu_idx, so_file_spec)) {
- // User zero as the ID to match the compile unit at offset
- // zero in each .o file since each .o file can only have
- // one compile unit for now.
+ // User zero as the ID to match the compile unit at offset zero in each
+ // .o file since each .o file can only have one compile unit for now.
lldb::user_id_t cu_id = 0;
m_compile_unit_infos[cu_idx].compile_unit_sp.reset(
new CompileUnit(m_obj_file->GetModule(), NULL, so_file_spec, cu_id,
@@ -767,8 +765,8 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t i = 0; i < cu_count; ++i) {
- // If we are checking for inlines, then we need to look through all
- // compile units no matter if "file_spec" matches.
+ // If we are checking for inlines, then we need to look through all compile
+ // units no matter if "file_spec" matches.
bool resolve = check_inlines;
if (!resolve) {
@@ -805,8 +803,8 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
if (comp_unit_info) {
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
if (oso_dwarf) {
- if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, true,
- max_matches, variables))
+ if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, max_matches,
+ variables))
if (variables.GetSize() > max_matches)
break;
}
@@ -817,21 +815,16 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables(
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches, VariableList &variables) {
+ uint32_t max_matches, VariableList &variables) {
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
uint32_t total_matches = 0;
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
const uint32_t oso_matches = oso_dwarf->FindGlobalVariables(
- name, parent_decl_ctx, true, max_matches, variables);
+ name, parent_decl_ctx, max_matches, variables);
if (oso_matches > 0) {
total_matches += oso_matches;
@@ -843,8 +836,8 @@ uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables(
if (max_matches >= total_matches)
return true;
- // Update the max matches for any subsequent calls to find globals
- // in any other object files with DWARF
+ // Update the max matches for any subsequent calls to find globals in any
+ // other object files with DWARF
max_matches -= oso_matches;
}
@@ -857,20 +850,15 @@ uint32_t SymbolFileDWARFDebugMap::FindGlobalVariables(
uint32_t
SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
VariableList &variables) {
- // If we aren't appending the results to this list, then clear the list
- if (!append)
- variables.Clear();
-
- // Remember how many variables are in the list before we search in case
- // we are appending the results to a variable list.
+ // Remember how many variables are in the list before we search.
const uint32_t original_size = variables.GetSize();
uint32_t total_matches = 0;
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
const uint32_t oso_matches =
- oso_dwarf->FindGlobalVariables(regex, true, max_matches, variables);
+ oso_dwarf->FindGlobalVariables(regex, max_matches, variables);
if (oso_matches > 0) {
total_matches += oso_matches;
@@ -882,8 +870,8 @@ SymbolFileDWARFDebugMap::FindGlobalVariables(const RegularExpression &regex,
if (max_matches >= total_matches)
return true;
- // Update the max matches for any subsequent calls to find globals
- // in any other object files with DWARF
+ // Update the max matches for any subsequent calls to find globals in any
+ // other object files with DWARF
max_matches -= oso_matches;
}
@@ -965,12 +953,12 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID(
static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp,
SymbolContextList &sc_list,
uint32_t start_idx) {
- // We found functions in .o files. Not all functions in the .o files
- // will have made it into the final output file. The ones that did
- // make it into the final output file will have a section whose module
- // matches the module from the ObjectFile for this SymbolFile. When
- // the modules don't match, then we have something that was in a
- // .o file, but doesn't map to anything in the final executable.
+ // We found functions in .o files. Not all functions in the .o files will
+ // have made it into the final output file. The ones that did make it into
+ // the final output file will have a section whose module matches the module
+ // from the ObjectFile for this SymbolFile. When the modules don't match,
+ // then we have something that was in a .o file, but doesn't map to anything
+ // in the final executable.
uint32_t i = start_idx;
while (i < sc_list.GetSize()) {
SymbolContext sc;
@@ -1101,12 +1089,12 @@ bool SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type(
TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
const DWARFDIE &die, const ConstString &type_name,
bool must_be_implementation) {
- // If we have a debug map, we will have an Objective C symbol whose name is
+ // If we have a debug map, we will have an Objective-C symbol whose name is
// the type name and whose type is eSymbolTypeObjCClass. If we can find that
// symbol and find its containing parent, we can locate the .o file that will
// contain the implementation definition since it will be scoped inside the
- // N_SO
- // and we can then locate the SymbolFileDWARF that corresponds to that N_SO.
+ // N_SO and we can then locate the SymbolFileDWARF that corresponds to that
+ // N_SO.
SymbolFileDWARF *oso_dwarf = NULL;
TypeSP type_sp;
ObjectFile *module_objfile = m_obj_file->GetModule()->GetObjectFile();
@@ -1118,8 +1106,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
Symtab::eVisibilityAny);
if (objc_class_symbol) {
// Get the N_SO symbol that contains the objective C class symbol as
- // this
- // should be the .o file that contains the real definition...
+ // this should be the .o file that contains the real definition...
const Symbol *source_file_symbol = symtab->GetParent(objc_class_symbol);
if (source_file_symbol &&
@@ -1147,10 +1134,8 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
}
// Only search all .o files for the definition if we don't need the
- // implementation
- // because otherwise, with a valid debug map we should have the ObjC class
- // symbol and
- // the code above should have found it.
+ // implementation because otherwise, with a valid debug map we should have
+ // the ObjC class symbol and the code above should have found it.
if (must_be_implementation == false) {
TypeSP type_sp;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index dcca4268b6eb..550f74a203ea 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -95,10 +95,10 @@ public:
uint32_t
FindGlobalVariables(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t
FindFunctions(const lldb_private::ConstString &name,
@@ -136,7 +136,7 @@ protected:
friend class DebugMapModule;
friend struct DIERef;
friend class DWARFASTParserClang;
- friend class DWARFCompileUnit;
+ friend class DWARFUnit;
friend class SymbolFileDWARF;
struct OSOInfo {
lldb::ModuleSP module_sp;
@@ -300,7 +300,9 @@ protected:
std::vector<CompileUnitInfo> m_compile_unit_infos;
std::vector<uint32_t> m_func_indexes; // Sorted by address
std::vector<uint32_t> m_glob_indexes;
- std::map<lldb_private::ConstString, OSOInfoSP> m_oso_map;
+ std::map<std::pair<lldb_private::ConstString, llvm::sys::TimePoint<>>,
+ OSOInfoSP>
+ m_oso_map;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
DebugMap m_debug_map;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index 17c188a41a77..15fe362fa117 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -14,14 +14,14 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
using namespace lldb;
using namespace lldb_private;
SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile,
- DWARFCompileUnit *dwarf_cu)
+ DWARFUnit *dwarf_cu)
: SymbolFileDWARF(objfile.get()), m_obj_file_sp(objfile),
m_base_dwarf_cu(dwarf_cu) {
SetID(((lldb::user_id_t)dwarf_cu->GetOffset()) << 32);
@@ -52,7 +52,7 @@ void SymbolFileDWARFDwo::LoadSectionData(lldb::SectionType sect_type,
}
lldb::CompUnitSP
-SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+SymbolFileDWARFDwo::ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) {
assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit "
"called with incompatible compile "
@@ -60,7 +60,7 @@ SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu, UINT32_MAX);
}
-DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() {
+DWARFUnit *SymbolFileDWARFDwo::GetCompileUnit() {
// A clang module is found via a skeleton CU, but is not a proper DWO.
// Clang modules have a .debug_info section instead of the *_dwo variant.
if (auto *section_list = m_obj_file->GetSectionList(false))
@@ -76,7 +76,7 @@ DWARFCompileUnit *SymbolFileDWARFDwo::GetCompileUnit() {
return nullptr;
}
-DWARFCompileUnit *
+DWARFUnit *
SymbolFileDWARFDwo::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) {
return GetCompileUnit();
}
@@ -122,7 +122,7 @@ lldb::TypeSP SymbolFileDWARFDwo::FindCompleteObjCDefinitionTypeForDIE(
die, type_name, must_be_implementation);
}
-DWARFCompileUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() {
+DWARFUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() {
return m_base_dwarf_cu;
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index b67967aafab2..483a19512a36 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -18,16 +18,16 @@
class SymbolFileDWARFDwo : public SymbolFileDWARF {
public:
- SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit *dwarf_cu);
+ SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu);
~SymbolFileDWARFDwo() override = default;
- lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit *dwarf_cu,
+ lldb::CompUnitSP ParseCompileUnit(DWARFUnit *dwarf_cu,
uint32_t cu_idx) override;
- DWARFCompileUnit *GetCompileUnit();
+ DWARFUnit *GetCompileUnit();
- DWARFCompileUnit *
+ DWARFUnit *
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override;
lldb_private::DWARFExpression::LocationListFormat
@@ -43,12 +43,12 @@ public:
GetDIE(const DIERef &die_ref) override;
std::unique_ptr<SymbolFileDWARFDwo>
- GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu,
+ GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
const DWARFDebugInfoEntry &cu_die) override {
return nullptr;
}
- DWARFCompileUnit *GetBaseCompileUnit() override;
+ DWARFUnit *GetBaseCompileUnit() override;
protected:
void LoadSectionData(lldb::SectionType sect_type,
@@ -74,7 +74,7 @@ protected:
SymbolFileDWARF *GetBaseSymbolFile();
lldb::ObjectFileSP m_obj_file_sp;
- DWARFCompileUnit *m_base_dwarf_cu;
+ DWARFUnit *m_base_dwarf_cu;
};
#endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
index f6de1818eae0..403c10fe65ea 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
@@ -14,7 +14,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/LLDBAssert.h"
-#include "DWARFCompileUnit.h"
+#include "DWARFUnit.h"
#include "DWARFDebugInfo.h"
using namespace lldb;
@@ -22,7 +22,7 @@ using namespace lldb_private;
SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
ObjectFileSP objfile,
- DWARFCompileUnit *dwarf_cu,
+ DWARFUnit *dwarf_cu,
uint64_t dwo_id)
: SymbolFileDWARFDwo(objfile, dwarf_cu), m_dwp_symfile(dwp_symfile),
m_dwo_id(dwo_id) {}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
index 00ad7aafd96b..b1b505b5899f 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
@@ -20,7 +20,7 @@
class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo {
public:
SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
- lldb::ObjectFileSP objfile, DWARFCompileUnit *dwarf_cu,
+ lldb::ObjectFileSP objfile, DWARFUnit *dwarf_cu,
uint64_t dwo_id);
protected:
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
index 1dc1dab34a5c..ae10e7179e33 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
@@ -85,7 +85,7 @@ SymbolFileDWARFDwp::SymbolFileDWARFDwp(lldb::ModuleSP module_sp,
{}
std::unique_ptr<SymbolFileDWARFDwo>
-SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu,
+SymbolFileDWARFDwp::GetSymbolFileForDwoId(DWARFUnit *dwarf_cu,
uint64_t dwo_id) {
return std::unique_ptr<SymbolFileDWARFDwo>(
new SymbolFileDWARFDwoDwp(this, m_obj_file, dwarf_cu, dwo_id));
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
index a7372b9358b1..470d1c5b1c48 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
@@ -29,7 +29,7 @@ public:
Create(lldb::ModuleSP module_sp, const lldb_private::FileSpec &file_spec);
std::unique_ptr<SymbolFileDWARFDwo>
- GetSymbolFileForDwoId(DWARFCompileUnit *dwarf_cu, uint64_t dwo_id);
+ GetSymbolFileForDwoId(DWARFUnit *dwarf_cu, uint64_t dwo_id);
bool LoadSectionData(uint64_t dwo_id, lldb::SectionType sect_type,
lldb_private::DWARFDataExtractor &data);
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 8697e08dbf86..8273d975e57d 100644
--- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -27,8 +27,8 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
udt.m_byte_size == byte_size) {
// Make sure the file and line match
if (udt.m_declaration == decl) {
- // The type has the same name, and was defined on the same
- // file and line. Now verify all of the parent DIEs match.
+ // The type has the same name, and was defined on the same file and
+ // line. Now verify all of the parent DIEs match.
DWARFDIE parent_arg_die = die.GetParent();
DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
@@ -57,6 +57,7 @@ bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
} break;
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
done = true;
break;
}
diff --git a/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/source/Plugins/SymbolFile/PDB/CMakeLists.txt
index 871f382298d6..1c176c32224d 100644
--- a/source/Plugins/SymbolFile/PDB/CMakeLists.txt
+++ b/source/Plugins/SymbolFile/PDB/CMakeLists.txt
@@ -1,5 +1,6 @@
add_lldb_library(lldbPluginSymbolFilePDB PLUGIN
PDBASTParser.cpp
+ PDBLocationToDWARFExpression.cpp
SymbolFilePDB.cpp
LINK_LIBS
diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index 7802d6f0d859..8bea994aae5d 100644
--- a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -19,19 +19,22 @@
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/TypeSystem.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
using namespace lldb;
using namespace lldb_private;
-using namespace llvm;
using namespace llvm::pdb;
namespace {
@@ -46,7 +49,7 @@ int TranslateUdtKind(PDB_UdtType pdb_kind) {
case PDB_UdtType::Interface:
return clang::TTK_Interface;
}
- return clang::TTK_Class;
+ return -1;
}
lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
@@ -58,16 +61,146 @@ lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
case PDB_BuiltinType::Char:
return lldb::eEncodingSint;
case PDB_BuiltinType::Bool:
+ case PDB_BuiltinType::Char16:
+ case PDB_BuiltinType::Char32:
case PDB_BuiltinType::UInt:
case PDB_BuiltinType::ULong:
case PDB_BuiltinType::HResult:
+ case PDB_BuiltinType::WCharT:
return lldb::eEncodingUint;
default:
return lldb::eEncodingInvalid;
}
}
+
+lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) {
+ switch (type) {
+ case PDB_VariantType::Int8:
+ case PDB_VariantType::Int16:
+ case PDB_VariantType::Int32:
+ case PDB_VariantType::Int64:
+ return lldb::eEncodingSint;
+
+ case PDB_VariantType::UInt8:
+ case PDB_VariantType::UInt16:
+ case PDB_VariantType::UInt32:
+ case PDB_VariantType::UInt64:
+ return lldb::eEncodingUint;
+
+ default:
+ break;
+ }
+
+ return lldb::eEncodingSint;
}
+CompilerType
+GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
+ const PDBSymbolTypeBuiltin &pdb_type,
+ Encoding encoding, uint32_t width) {
+ auto *ast = clang_ast.getASTContext();
+ if (!ast)
+ return CompilerType();
+
+ switch (pdb_type.getBuiltinType()) {
+ default:
+ break;
+ case PDB_BuiltinType::None:
+ return CompilerType();
+ case PDB_BuiltinType::Void:
+ return clang_ast.GetBasicType(eBasicTypeVoid);
+ case PDB_BuiltinType::Bool:
+ return clang_ast.GetBasicType(eBasicTypeBool);
+ case PDB_BuiltinType::Long:
+ if (width == ast->getTypeSize(ast->LongTy))
+ return CompilerType(ast, ast->LongTy);
+ if (width == ast->getTypeSize(ast->LongLongTy))
+ return CompilerType(ast, ast->LongLongTy);
+ break;
+ case PDB_BuiltinType::ULong:
+ if (width == ast->getTypeSize(ast->UnsignedLongTy))
+ return CompilerType(ast, ast->UnsignedLongTy);
+ if (width == ast->getTypeSize(ast->UnsignedLongLongTy))
+ return CompilerType(ast, ast->UnsignedLongLongTy);
+ break;
+ case PDB_BuiltinType::WCharT:
+ if (width == ast->getTypeSize(ast->WCharTy))
+ return CompilerType(ast, ast->WCharTy);
+ break;
+ case PDB_BuiltinType::Char16:
+ return CompilerType(ast, ast->Char16Ty);
+ case PDB_BuiltinType::Char32:
+ return CompilerType(ast, ast->Char32Ty);
+ case PDB_BuiltinType::Float:
+ // Note: types `long double` and `double` have same bit size in MSVC and
+ // there is no information in the PDB to distinguish them. So when falling
+ // back to default search, the compiler type of `long double` will be
+ // represented by the one generated for `double`.
+ break;
+ }
+ // If there is no match on PDB_BuiltinType, fall back to default search by
+ // encoding and width only
+ return clang_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
+}
+
+ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type,
+ CompilerType &compiler_type) {
+ PDB_BuiltinType kind = pdb_type.getBuiltinType();
+ switch (kind) {
+ default:
+ break;
+ case PDB_BuiltinType::Currency:
+ return ConstString("CURRENCY");
+ case PDB_BuiltinType::Date:
+ return ConstString("DATE");
+ case PDB_BuiltinType::Variant:
+ return ConstString("VARIANT");
+ case PDB_BuiltinType::Complex:
+ return ConstString("complex");
+ case PDB_BuiltinType::Bitfield:
+ return ConstString("bitfield");
+ case PDB_BuiltinType::BSTR:
+ return ConstString("BSTR");
+ case PDB_BuiltinType::HResult:
+ return ConstString("HRESULT");
+ case PDB_BuiltinType::BCD:
+ return ConstString("BCD");
+ case PDB_BuiltinType::Char16:
+ return ConstString("char16_t");
+ case PDB_BuiltinType::Char32:
+ return ConstString("char32_t");
+ case PDB_BuiltinType::None:
+ return ConstString("...");
+ }
+ return compiler_type.GetTypeName();
+}
+
+bool GetDeclarationForSymbol(const PDBSymbol &symbol, Declaration &decl) {
+ auto &raw_sym = symbol.getRawSymbol();
+ auto first_line_up = raw_sym.getSrcLineOnTypeDefn();
+
+ if (!first_line_up) {
+ auto lines_up = symbol.getSession().findLineNumbersByAddress(
+ raw_sym.getVirtualAddress(), raw_sym.getLength());
+ if (!lines_up)
+ return false;
+ first_line_up = lines_up->getNext();
+ if (!first_line_up)
+ return false;
+ }
+ uint32_t src_file_id = first_line_up->getSourceFileId();
+ auto src_file_up = symbol.getSession().getSourceFileById(src_file_id);
+ if (!src_file_up)
+ return false;
+
+ FileSpec spec(src_file_up->getFileName(), /*resolve_path*/ false);
+ decl.SetFile(spec);
+ decl.SetColumn(first_line_up->getColumnNumber());
+ decl.SetLine(first_line_up->getLineNumber());
+ return true;
+}
+} // namespace
+
PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) {}
PDBASTParser::~PDBASTParser() {}
@@ -76,21 +209,27 @@ PDBASTParser::~PDBASTParser() {}
lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
// PDB doesn't maintain enough information to robustly rebuild the entire
- // tree, and this is most problematic when it comes to figure out the
- // right DeclContext to put a type in. So for now, everything goes in
- // the translation unit decl as a fully qualified type.
+ // tree, and this is most problematic when it comes to figure out the right
+ // DeclContext to put a type in. So for now, everything goes in the
+ // translation unit decl as a fully qualified type.
clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl();
Declaration decl;
- if (auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type)) {
+ switch (type.getSymTag()) {
+ case PDB_SymType::UDT: {
+ auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type);
+ assert(udt);
AccessType access = lldb::eAccessPublic;
PDB_UdtType udt_kind = udt->getUdtKind();
+ auto tag_type_kind = TranslateUdtKind(udt_kind);
+ if (tag_type_kind == -1)
+ return nullptr;
if (udt_kind == PDB_UdtType::Class)
access = lldb::eAccessPrivate;
CompilerType clang_type = m_ast.CreateRecordType(
- tu_decl_ctx, access, udt->getName().c_str(), TranslateUdtKind(udt_kind),
+ tu_decl_ctx, access, udt->getName().c_str(), tag_type_kind,
lldb::eLanguageTypeC_plus_plus, nullptr);
m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
@@ -100,51 +239,107 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
ConstString(udt->getName()), udt->getLength(), nullptr,
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type,
lldb_private::Type::eResolveStateForward);
- } else if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type)) {
- std::string name = enum_type->getName();
+ } break;
+ case PDB_SymType::Enum: {
+ auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
+ assert(enum_type);
+ auto underlying_type_up = enum_type->getUnderlyingType();
+ if (!underlying_type_up)
+ return nullptr;
lldb::Encoding encoding =
- TranslateBuiltinEncoding(enum_type->getBuiltinType());
+ TranslateBuiltinEncoding(underlying_type_up->getBuiltinType());
+ // FIXME: Type of underlying builtin is always `Int`. We correct it with
+ // the very first enumerator's encoding if any.
+ auto first_child = enum_type->findOneChild<PDBSymbolData>();
+ if (first_child) {
+ encoding = TranslateEnumEncoding(first_child->getValue().Type);
+ }
+ std::string name = enum_type->getName();
uint64_t bytes = enum_type->getLength();
- CompilerType builtin_type =
- m_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bytes * 8);
+ CompilerType builtin_type;
+ if (bytes > 0)
+ builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize(
+ m_ast, *underlying_type_up, encoding, bytes * 8);
+ else
+ builtin_type = m_ast.GetBasicType(eBasicTypeInt);
+ // FIXME: PDB does not have information about scoped enumeration (Enum
+ // Class). Set it false for now.
+ bool isScoped = false;
CompilerType ast_enum = m_ast.CreateEnumerationType(
- name.c_str(), tu_decl_ctx, decl, builtin_type, false);
+ name.c_str(), tu_decl_ctx, decl, builtin_type, isScoped);
auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
- while (auto enum_value = enum_values->getNext()) {
- if (enum_value->getDataKind() != PDB_DataKind::Constant)
- continue;
- AddEnumValue(ast_enum, *enum_value);
+ if (enum_values) {
+ while (auto enum_value = enum_values->getNext()) {
+ if (enum_value->getDataKind() != PDB_DataKind::Constant)
+ continue;
+ AddEnumValue(ast_enum, *enum_value);
+ }
}
+ if (ClangASTContext::StartTagDeclarationDefinition(ast_enum))
+ ClangASTContext::CompleteTagDeclarationDefinition(ast_enum);
+ GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
ast_enum, lldb_private::Type::eResolveStateFull);
- } else if (auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type)) {
+ } break;
+ case PDB_SymType::Typedef: {
+ auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
+ assert(type_def);
lldb_private::Type *target_type =
m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
if (!target_type)
return nullptr;
std::string name = type_def->getName();
uint64_t bytes = type_def->getLength();
- if (!target_type)
- return nullptr;
CompilerType target_ast_type = target_type->GetFullCompilerType();
CompilerDeclContext target_decl_ctx =
m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
CompilerType ast_typedef =
m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
+ if (!ast_typedef)
+ return nullptr;
+
return std::make_shared<lldb_private::Type>(
type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
bytes, nullptr, target_type->GetID(),
lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef,
lldb_private::Type::eResolveStateFull);
- } else if (auto func_sig = llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
+ } break;
+ case PDB_SymType::Function:
+ case PDB_SymType::FunctionSig: {
+ std::string name;
+ PDBSymbolTypeFunctionSig *func_sig = nullptr;
+ if (auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(&type)) {
+ if (pdb_func->isCompilerGenerated())
+ return nullptr;
+
+ auto sig = pdb_func->getSignature();
+ if (!sig)
+ return nullptr;
+ func_sig = sig.release();
+ // Function type is named.
+ name = pdb_func->getName();
+ } else if (auto pdb_func_sig =
+ llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
+ func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig);
+ } else
+ llvm_unreachable("Unexpected PDB symbol!");
+
auto arg_enum = func_sig->getArguments();
uint32_t num_args = arg_enum->getChildCount();
- std::vector<CompilerType> arg_list(num_args);
- while (auto arg = arg_enum->getNext()) {
+ std::vector<CompilerType> arg_list;
+
+ bool is_variadic = func_sig->isCVarArgs();
+ // Drop last variadic argument.
+ if (is_variadic)
+ --num_args;
+ for (uint32_t arg_idx = 0; arg_idx < num_args; arg_idx++) {
+ auto arg = arg_enum->getChildAtIndex(arg_idx);
+ if (!arg)
+ break;
lldb_private::Type *arg_type =
m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId());
// If there's some error looking up one of the dependent types of this
@@ -154,6 +349,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
CompilerType arg_ast_type = arg_type->GetFullCompilerType();
arg_list.push_back(arg_ast_type);
}
+ lldbassert(arg_list.size() <= num_args);
+
auto pdb_return_type = func_sig->getReturnType();
lldb_private::Type *return_type =
m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId());
@@ -167,29 +364,109 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type_quals |= clang::Qualifiers::Const;
if (func_sig->isVolatileType())
type_quals |= clang::Qualifiers::Volatile;
- CompilerType func_sig_ast_type = m_ast.CreateFunctionType(
- return_ast_type, &arg_list[0], num_args, false, type_quals);
+ CompilerType func_sig_ast_type =
+ m_ast.CreateFunctionType(return_ast_type, arg_list.data(),
+ arg_list.size(), is_variadic, type_quals);
+ GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
- func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0,
+ type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), 0,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
func_sig_ast_type, lldb_private::Type::eResolveStateFull);
- } else if (auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type)) {
+ } break;
+ case PDB_SymType::ArrayType: {
+ auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type);
+ assert(array_type);
uint32_t num_elements = array_type->getCount();
- uint32_t element_uid = array_type->getElementType()->getSymIndexId();
+ uint32_t element_uid = array_type->getElementTypeId();
uint32_t bytes = array_type->getLength();
+ // If array rank > 0, PDB gives the element type at N=0. So element type
+ // will parsed in the order N=0, N=1,..., N=rank sequentially.
lldb_private::Type *element_type =
m_ast.GetSymbolFile()->ResolveTypeUID(element_uid);
if (!element_type)
return nullptr;
- CompilerType element_ast_type = element_type->GetFullCompilerType();
- CompilerType array_ast_type =
- m_ast.CreateArrayType(element_ast_type, num_elements, false);
- return std::make_shared<lldb_private::Type>(
+
+ CompilerType element_ast_type = element_type->GetForwardCompilerType();
+ // If element type is UDT, it needs to be complete.
+ if (ClangASTContext::IsCXXClassType(element_ast_type) &&
+ element_ast_type.GetCompleteType() == false) {
+ if (ClangASTContext::StartTagDeclarationDefinition(element_ast_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(element_ast_type);
+ } else {
+ // We are not able to start defintion.
+ return nullptr;
+ }
+ }
+ CompilerType array_ast_type = m_ast.CreateArrayType(
+ element_ast_type, num_elements, /*is_gnu_vector*/ false);
+ TypeSP type_sp = std::make_shared<lldb_private::Type>(
array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
decl, array_ast_type, lldb_private::Type::eResolveStateFull);
+ type_sp->SetEncodingType(element_type);
+ return type_sp;
+ } break;
+ case PDB_SymType::BuiltinType: {
+ auto *builtin_type = llvm::dyn_cast<PDBSymbolTypeBuiltin>(&type);
+ assert(builtin_type);
+ PDB_BuiltinType builtin_kind = builtin_type->getBuiltinType();
+ if (builtin_kind == PDB_BuiltinType::None)
+ return nullptr;
+
+ uint64_t bytes = builtin_type->getLength();
+ Encoding encoding = TranslateBuiltinEncoding(builtin_kind);
+ CompilerType builtin_ast_type = GetBuiltinTypeForPDBEncodingAndBitSize(
+ m_ast, *builtin_type, encoding, bytes * 8);
+
+ if (builtin_type->isConstType())
+ builtin_ast_type = builtin_ast_type.AddConstModifier();
+
+ if (builtin_type->isVolatileType())
+ builtin_ast_type = builtin_ast_type.AddVolatileModifier();
+
+ auto type_name = GetPDBBuiltinTypeName(*builtin_type, builtin_ast_type);
+
+ return std::make_shared<lldb_private::Type>(
+ builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name, bytes,
+ nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
+ builtin_ast_type, lldb_private::Type::eResolveStateFull);
+ } break;
+ case PDB_SymType::PointerType: {
+ auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
+ assert(pointer_type);
+ Type *pointee_type = m_ast.GetSymbolFile()->ResolveTypeUID(
+ pointer_type->getPointeeType()->getSymIndexId());
+ if (!pointee_type)
+ return nullptr;
+
+ CompilerType pointer_ast_type;
+ pointer_ast_type = pointee_type->GetFullCompilerType();
+ if (pointer_type->isReference())
+ pointer_ast_type = pointer_ast_type.GetLValueReferenceType();
+ else if (pointer_type->isRValueReference())
+ pointer_ast_type = pointer_ast_type.GetRValueReferenceType();
+ else
+ pointer_ast_type = pointer_ast_type.GetPointerType();
+
+ if (pointer_type->isConstType())
+ pointer_ast_type = pointer_ast_type.AddConstModifier();
+
+ if (pointer_type->isVolatileType())
+ pointer_ast_type = pointer_ast_type.AddVolatileModifier();
+
+ if (pointer_type->isRestrictedType())
+ pointer_ast_type = pointer_ast_type.AddRestrictModifier();
+
+ return std::make_shared<lldb_private::Type>(
+ pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
+ pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
+ lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
+ lldb_private::Type::eResolveStateFull);
+ } break;
+ default:
+ break;
}
return nullptr;
}
diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.h b/source/Plugins/SymbolFile/PDB/PDBASTParser.h
index e9ff02c0a77e..d1ac138b8115 100644
--- a/source/Plugins/SymbolFile/PDB/PDBASTParser.h
+++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.h
@@ -19,20 +19,20 @@ class CharUnits;
class CXXRecordDecl;
class FieldDecl;
class RecordDecl;
-}
+} // namespace clang
namespace lldb_private {
class ClangASTContext;
class CompilerType;
-}
+} // namespace lldb_private
namespace llvm {
namespace pdb {
class PDBSymbol;
class PDBSymbolData;
class PDBSymbolTypeBuiltin;
-}
-}
+} // namespace pdb
+} // namespace llvm
class PDBASTParser {
public:
@@ -49,4 +49,4 @@ private:
lldb_private::ClangASTImporter m_ast_importer;
};
-#endif // SymbolFileDWARF_DWARFASTParserClang_h_
+#endif // LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H
diff --git a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
new file mode 100644
index 000000000000..69ef70cc508c
--- /dev/null
+++ b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
@@ -0,0 +1,585 @@
+//===-- PDBLocationToDWARFExpression.cpp ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PDBLocationToDWARFExpression.h"
+
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamBuffer.h"
+#include "lldb/Core/dwarf.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Utility/DataBufferHeap.h"
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm::pdb;
+
+namespace {
+const uint32_t g_code_view_to_lldb_registers_x86[] = {
+ LLDB_INVALID_REGNUM, // CVRegNONE
+ lldb_al_i386, // CVRegAL
+ lldb_cl_i386, // CVRegCL
+ lldb_dl_i386, // CVRegDL
+ lldb_bl_i386, // CVRegBL
+ lldb_ah_i386, // CVRegAH
+ lldb_ch_i386, // CVRegCH
+ lldb_dh_i386, // CVRegDH
+ lldb_bh_i386, // CVRegBH
+ lldb_ax_i386, // CVRegAX
+ lldb_cx_i386, // CVRegCX
+ lldb_dx_i386, // CVRegDX
+ lldb_bx_i386, // CVRegBX
+ lldb_sp_i386, // CVRegSP
+ lldb_bp_i386, // CVRegBP
+ lldb_si_i386, // CVRegSI
+ lldb_di_i386, // CVRegDI
+ lldb_eax_i386, // CVRegEAX
+ lldb_ecx_i386, // CVRegECX
+ lldb_edx_i386, // CVRegEDX
+ lldb_ebx_i386, // CVRegEBX
+ lldb_esp_i386, // CVRegESP
+ lldb_ebp_i386, // CVRegEBP
+ lldb_esi_i386, // CVRegESI
+ lldb_edi_i386, // CVRegEDI
+ lldb_es_i386, // CVRegES
+ lldb_cs_i386, // CVRegCS
+ lldb_ss_i386, // CVRegSS
+ lldb_ds_i386, // CVRegDS
+ lldb_fs_i386, // CVRegFS
+ lldb_gs_i386, // CVRegGS
+ LLDB_INVALID_REGNUM, // CVRegIP
+ LLDB_INVALID_REGNUM, // CVRegFLAGS
+ lldb_eip_i386, // CVRegEIP
+ lldb_eflags_i386, // CVRegEFLAGS
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegTEMP
+ LLDB_INVALID_REGNUM, // CVRegTEMPH
+ LLDB_INVALID_REGNUM, // CVRegQUOTE
+ LLDB_INVALID_REGNUM, // CVRegPCDR3
+ LLDB_INVALID_REGNUM, // CVRegPCDR4
+ LLDB_INVALID_REGNUM, // CVRegPCDR5
+ LLDB_INVALID_REGNUM, // CVRegPCDR6
+ LLDB_INVALID_REGNUM, // CVRegPCDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegCR0
+ LLDB_INVALID_REGNUM, // CVRegCR1
+ LLDB_INVALID_REGNUM, // CVRegCR2
+ LLDB_INVALID_REGNUM, // CVRegCR3
+ LLDB_INVALID_REGNUM, // CVRegCR4
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_dr0_i386, // CVRegDR0
+ lldb_dr1_i386, // CVRegDR1
+ lldb_dr2_i386, // CVRegDR2
+ lldb_dr3_i386, // CVRegDR3
+ lldb_dr4_i386, // CVRegDR4
+ lldb_dr5_i386, // CVRegDR5
+ lldb_dr6_i386, // CVRegDR6
+ lldb_dr7_i386, // CVRegDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegGDTR
+ LLDB_INVALID_REGNUM, // CVRegGDTL
+ LLDB_INVALID_REGNUM, // CVRegIDTR
+ LLDB_INVALID_REGNUM, // CVRegIDTL
+ LLDB_INVALID_REGNUM, // CVRegLDTR
+ LLDB_INVALID_REGNUM, // CVRegTR
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO1
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO2
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO3
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO4
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO5
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO6
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO7
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO8
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO9
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_st0_i386, // CVRegST0
+ lldb_st1_i386, // CVRegST1
+ lldb_st2_i386, // CVRegST2
+ lldb_st3_i386, // CVRegST3
+ lldb_st4_i386, // CVRegST4
+ lldb_st5_i386, // CVRegST5
+ lldb_st6_i386, // CVRegST6
+ lldb_st7_i386, // CVRegST7
+ LLDB_INVALID_REGNUM, // CVRegCTRL
+ LLDB_INVALID_REGNUM, // CVRegSTAT
+ LLDB_INVALID_REGNUM, // CVRegTAG
+ LLDB_INVALID_REGNUM, // CVRegFPIP
+ LLDB_INVALID_REGNUM, // CVRegFPCS
+ LLDB_INVALID_REGNUM, // CVRegFPDO
+ LLDB_INVALID_REGNUM, // CVRegFPDS
+ LLDB_INVALID_REGNUM, // CVRegISEM
+ LLDB_INVALID_REGNUM, // CVRegFPEIP
+ LLDB_INVALID_REGNUM, // CVRegFPEDO
+ lldb_mm0_i386, // CVRegMM0
+ lldb_mm1_i386, // CVRegMM1
+ lldb_mm2_i386, // CVRegMM2
+ lldb_mm3_i386, // CVRegMM3
+ lldb_mm4_i386, // CVRegMM4
+ lldb_mm5_i386, // CVRegMM5
+ lldb_mm6_i386, // CVRegMM6
+ lldb_mm7_i386, // CVRegMM7
+ lldb_xmm0_i386, // CVRegXMM0
+ lldb_xmm1_i386, // CVRegXMM1
+ lldb_xmm2_i386, // CVRegXMM2
+ lldb_xmm3_i386, // CVRegXMM3
+ lldb_xmm4_i386, // CVRegXMM4
+ lldb_xmm5_i386, // CVRegXMM5
+ lldb_xmm6_i386, // CVRegXMM6
+ lldb_xmm7_i386 // CVRegXMM7
+};
+
+const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
+ LLDB_INVALID_REGNUM, // CVRegNONE
+ lldb_al_x86_64, // CVRegAL
+ lldb_cl_x86_64, // CVRegCL
+ lldb_dl_x86_64, // CVRegDL
+ lldb_bl_x86_64, // CVRegBL
+ lldb_ah_x86_64, // CVRegAH
+ lldb_ch_x86_64, // CVRegCH
+ lldb_dh_x86_64, // CVRegDH
+ lldb_bh_x86_64, // CVRegBH
+ lldb_ax_x86_64, // CVRegAX
+ lldb_cx_x86_64, // CVRegCX
+ lldb_dx_x86_64, // CVRegDX
+ lldb_bx_x86_64, // CVRegBX
+ lldb_sp_x86_64, // CVRegSP
+ lldb_bp_x86_64, // CVRegBP
+ lldb_si_x86_64, // CVRegSI
+ lldb_di_x86_64, // CVRegDI
+ lldb_eax_x86_64, // CVRegEAX
+ lldb_ecx_x86_64, // CVRegECX
+ lldb_edx_x86_64, // CVRegEDX
+ lldb_ebx_x86_64, // CVRegEBX
+ lldb_esp_x86_64, // CVRegESP
+ lldb_ebp_x86_64, // CVRegEBP
+ lldb_esi_x86_64, // CVRegESI
+ lldb_edi_x86_64, // CVRegEDI
+ lldb_es_x86_64, // CVRegES
+ lldb_cs_x86_64, // CVRegCS
+ lldb_ss_x86_64, // CVRegSS
+ lldb_ds_x86_64, // CVRegDS
+ lldb_fs_x86_64, // CVRegFS
+ lldb_gs_x86_64, // CVRegGS
+ LLDB_INVALID_REGNUM, // CVRegIP
+ LLDB_INVALID_REGNUM, // CVRegFLAGS
+ LLDB_INVALID_REGNUM, // CVRegEIP
+ LLDB_INVALID_REGNUM, // CVRegEFLAGS
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegTEMP
+ LLDB_INVALID_REGNUM, // CVRegTEMPH
+ LLDB_INVALID_REGNUM, // CVRegQUOTE
+ LLDB_INVALID_REGNUM, // CVRegPCDR3
+ LLDB_INVALID_REGNUM, // CVRegPCDR4
+ LLDB_INVALID_REGNUM, // CVRegPCDR5
+ LLDB_INVALID_REGNUM, // CVRegPCDR6
+ LLDB_INVALID_REGNUM, // CVRegPCDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegCR0
+ LLDB_INVALID_REGNUM, // CVRegCR1
+ LLDB_INVALID_REGNUM, // CVRegCR2
+ LLDB_INVALID_REGNUM, // CVRegCR3
+ LLDB_INVALID_REGNUM, // CVRegCR4
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_dr0_x86_64, // CVRegDR0
+ lldb_dr1_x86_64, // CVRegDR1
+ lldb_dr2_x86_64, // CVRegDR2
+ lldb_dr3_x86_64, // CVRegDR3
+ lldb_dr4_x86_64, // CVRegDR4
+ lldb_dr5_x86_64, // CVRegDR5
+ lldb_dr6_x86_64, // CVRegDR6
+ lldb_dr7_x86_64, // CVRegDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegGDTR
+ LLDB_INVALID_REGNUM, // CVRegGDTL
+ LLDB_INVALID_REGNUM, // CVRegIDTR
+ LLDB_INVALID_REGNUM, // CVRegIDTL
+ LLDB_INVALID_REGNUM, // CVRegLDTR
+ LLDB_INVALID_REGNUM, // CVRegTR
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO1
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO2
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO3
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO4
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO5
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO6
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO7
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO8
+ LLDB_INVALID_REGNUM, // CVRegPSEUDO9
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_st0_x86_64, // CVRegST0
+ lldb_st1_x86_64, // CVRegST1
+ lldb_st2_x86_64, // CVRegST2
+ lldb_st3_x86_64, // CVRegST3
+ lldb_st4_x86_64, // CVRegST4
+ lldb_st5_x86_64, // CVRegST5
+ lldb_st6_x86_64, // CVRegST6
+ lldb_st7_x86_64, // CVRegST7
+ LLDB_INVALID_REGNUM, // CVRegCTRL
+ LLDB_INVALID_REGNUM, // CVRegSTAT
+ LLDB_INVALID_REGNUM, // CVRegTAG
+ LLDB_INVALID_REGNUM, // CVRegFPIP
+ LLDB_INVALID_REGNUM, // CVRegFPCS
+ LLDB_INVALID_REGNUM, // CVRegFPDO
+ LLDB_INVALID_REGNUM, // CVRegFPDS
+ LLDB_INVALID_REGNUM, // CVRegISEM
+ LLDB_INVALID_REGNUM, // CVRegFPEIP
+ LLDB_INVALID_REGNUM, // CVRegFPEDO
+ lldb_mm0_x86_64, // CVRegMM0
+ lldb_mm1_x86_64, // CVRegMM1
+ lldb_mm2_x86_64, // CVRegMM2
+ lldb_mm3_x86_64, // CVRegMM3
+ lldb_mm4_x86_64, // CVRegMM4
+ lldb_mm5_x86_64, // CVRegMM5
+ lldb_mm6_x86_64, // CVRegMM6
+ lldb_mm7_x86_64, // CVRegMM7
+ lldb_xmm0_x86_64, // CVRegXMM0
+ lldb_xmm1_x86_64, // CVRegXMM1
+ lldb_xmm2_x86_64, // CVRegXMM2
+ lldb_xmm3_x86_64, // CVRegXMM3
+ lldb_xmm4_x86_64, // CVRegXMM4
+ lldb_xmm5_x86_64, // CVRegXMM5
+ lldb_xmm6_x86_64, // CVRegXMM6
+ lldb_xmm7_x86_64, // CVRegXMM7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ lldb_mxcsr_x86_64, // CVRegMXCSR
+ LLDB_INVALID_REGNUM, // CVRegEDXEAX
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CVRegEMM0L
+ LLDB_INVALID_REGNUM, // CVRegEMM1L
+ LLDB_INVALID_REGNUM, // CVRegEMM2L
+ LLDB_INVALID_REGNUM, // CVRegEMM3L
+ LLDB_INVALID_REGNUM, // CVRegEMM4L
+ LLDB_INVALID_REGNUM, // CVRegEMM5L
+ LLDB_INVALID_REGNUM, // CVRegEMM6L
+ LLDB_INVALID_REGNUM, // CVRegEMM7L
+ LLDB_INVALID_REGNUM, // CVRegEMM0H
+ LLDB_INVALID_REGNUM, // CVRegEMM1H
+ LLDB_INVALID_REGNUM, // CVRegEMM2H
+ LLDB_INVALID_REGNUM, // CVRegEMM3H
+ LLDB_INVALID_REGNUM, // CVRegEMM4H
+ LLDB_INVALID_REGNUM, // CVRegEMM5H
+ LLDB_INVALID_REGNUM, // CVRegEMM6H
+ LLDB_INVALID_REGNUM, // CVRegEMM7H
+ LLDB_INVALID_REGNUM, // CVRegMM00
+ LLDB_INVALID_REGNUM, // CVRegMM01
+ LLDB_INVALID_REGNUM, // CVRegMM10
+ LLDB_INVALID_REGNUM, // CVRegMM11
+ LLDB_INVALID_REGNUM, // CVRegMM20
+ LLDB_INVALID_REGNUM, // CVRegMM21
+ LLDB_INVALID_REGNUM, // CVRegMM30
+ LLDB_INVALID_REGNUM, // CVRegMM31
+ LLDB_INVALID_REGNUM, // CVRegMM40
+ LLDB_INVALID_REGNUM, // CVRegMM41
+ LLDB_INVALID_REGNUM, // CVRegMM50
+ LLDB_INVALID_REGNUM, // CVRegMM51
+ LLDB_INVALID_REGNUM, // CVRegMM60
+ LLDB_INVALID_REGNUM, // CVRegMM61
+ LLDB_INVALID_REGNUM, // CVRegMM70
+ LLDB_INVALID_REGNUM, // CVRegMM71
+ lldb_xmm8_x86_64, // CVRegXMM8
+ lldb_xmm9_x86_64, // CVRegXMM9
+ lldb_xmm10_x86_64, // CVRegXMM10
+ lldb_xmm11_x86_64, // CVRegXMM11
+ lldb_xmm12_x86_64, // CVRegXMM12
+ lldb_xmm13_x86_64, // CVRegXMM13
+ lldb_xmm14_x86_64, // CVRegXMM14
+ lldb_xmm15_x86_64, // CVRegXMM15
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ lldb_sil_x86_64, // CVRegSIL
+ lldb_dil_x86_64, // CVRegDIL
+ lldb_bpl_x86_64, // CVRegBPL
+ lldb_spl_x86_64, // CVRegSPL
+ lldb_rax_x86_64, // CVRegRAX
+ lldb_rbx_x86_64, // CVRegRBX
+ lldb_rcx_x86_64, // CVRegRCX
+ lldb_rdx_x86_64, // CVRegRDX
+ lldb_rsi_x86_64, // CVRegRSI
+ lldb_rdi_x86_64, // CVRegRDI
+ lldb_rbp_x86_64, // CVRegRBP
+ lldb_rsp_x86_64, // CVRegRSP
+ lldb_r8_x86_64, // CVRegR8
+ lldb_r9_x86_64, // CVRegR9
+ lldb_r10_x86_64, // CVRegR10
+ lldb_r11_x86_64, // CVRegR11
+ lldb_r12_x86_64, // CVRegR12
+ lldb_r13_x86_64, // CVRegR13
+ lldb_r14_x86_64, // CVRegR14
+ lldb_r15_x86_64, // CVRegR15
+ lldb_r8l_x86_64, // CVRegR8B
+ lldb_r9l_x86_64, // CVRegR9B
+ lldb_r10l_x86_64, // CVRegR10B
+ lldb_r11l_x86_64, // CVRegR11B
+ lldb_r12l_x86_64, // CVRegR12B
+ lldb_r13l_x86_64, // CVRegR13B
+ lldb_r14l_x86_64, // CVRegR14B
+ lldb_r15l_x86_64, // CVRegR15B
+ lldb_r8w_x86_64, // CVRegR8W
+ lldb_r9w_x86_64, // CVRegR9W
+ lldb_r10w_x86_64, // CVRegR10W
+ lldb_r11w_x86_64, // CVRegR11W
+ lldb_r12w_x86_64, // CVRegR12W
+ lldb_r13w_x86_64, // CVRegR13W
+ lldb_r14w_x86_64, // CVRegR14W
+ lldb_r15w_x86_64, // CVRegR15W
+ lldb_r8d_x86_64, // CVRegR8D
+ lldb_r9d_x86_64, // CVRegR9D
+ lldb_r10d_x86_64, // CVRegR10D
+ lldb_r11d_x86_64, // CVRegR11D
+ lldb_r12d_x86_64, // CVRegR12D
+ lldb_r13d_x86_64, // CVRegR13D
+ lldb_r14d_x86_64, // CVRegR14D
+ lldb_r15d_x86_64, // CVRegR15D
+ lldb_ymm0_x86_64, // CVRegAMD64_YMM0
+ lldb_ymm1_x86_64, // CVRegAMD64_YMM1
+ lldb_ymm2_x86_64, // CVRegAMD64_YMM2
+ lldb_ymm3_x86_64, // CVRegAMD64_YMM3
+ lldb_ymm4_x86_64, // CVRegAMD64_YMM4
+ lldb_ymm5_x86_64, // CVRegAMD64_YMM5
+ lldb_ymm6_x86_64, // CVRegAMD64_YMM6
+ lldb_ymm7_x86_64, // CVRegAMD64_YMM7
+ lldb_ymm8_x86_64, // CVRegAMD64_YMM8
+ lldb_ymm9_x86_64, // CVRegAMD64_YMM9
+ lldb_ymm10_x86_64, // CVRegAMD64_YMM10
+ lldb_ymm11_x86_64, // CVRegAMD64_YMM11
+ lldb_ymm12_x86_64, // CVRegAMD64_YMM12
+ lldb_ymm13_x86_64, // CVRegAMD64_YMM13
+ lldb_ymm14_x86_64, // CVRegAMD64_YMM14
+ lldb_ymm15_x86_64, // CVRegAMD64_YMM15
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_bnd0_x86_64, // CVRegBND0
+ lldb_bnd1_x86_64, // CVRegBND1
+ lldb_bnd2_x86_64 // CVRegBND2
+};
+
+uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
+ llvm::codeview::RegisterId register_id) {
+ switch (arch_type) {
+ case llvm::Triple::x86:
+ if (static_cast<uint16_t>(register_id) <
+ sizeof(g_code_view_to_lldb_registers_x86) /
+ sizeof(g_code_view_to_lldb_registers_x86[0]))
+ return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>(
+ register_id)];
+
+ switch (register_id) {
+ case llvm::codeview::RegisterId::CVRegMXCSR:
+ return lldb_mxcsr_i386;
+ case llvm::codeview::RegisterId::CVRegBND0:
+ return lldb_bnd0_i386;
+ case llvm::codeview::RegisterId::CVRegBND1:
+ return lldb_bnd1_i386;
+ case llvm::codeview::RegisterId::CVRegBND2:
+ return lldb_bnd2_i386;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ case llvm::Triple::x86_64:
+ if (static_cast<uint16_t>(register_id) <
+ sizeof(g_code_view_to_lldb_registers_x86_64) /
+ sizeof(g_code_view_to_lldb_registers_x86_64[0]))
+ return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>(
+ register_id)];
+
+ return LLDB_INVALID_REGNUM;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+}
+
+uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
+ if (register_id == llvm::codeview::RegisterId::CVRegVFRAME)
+ return LLDB_REGNUM_GENERIC_FP;
+
+ return LLDB_INVALID_REGNUM;
+}
+
+uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
+ llvm::codeview::RegisterId register_id,
+ RegisterKind &register_kind) {
+ register_kind = eRegisterKindLLDB;
+ uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
+ if (reg_num != LLDB_INVALID_REGNUM)
+ return reg_num;
+
+ register_kind = eRegisterKindGeneric;
+ return GetGenericRegisterNumber(register_id);
+}
+} // namespace
+
+DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module,
+ const PDBSymbolData &symbol,
+ bool &is_constant) {
+ is_constant = true;
+
+ if (!module)
+ return DWARFExpression(nullptr);
+
+ const ArchSpec &architecture = module->GetArchitecture();
+ llvm::Triple::ArchType arch_type = architecture.GetMachine();
+ ByteOrder byte_order = architecture.GetByteOrder();
+ uint32_t address_size = architecture.GetAddressByteSize();
+ uint32_t byte_size = architecture.GetDataByteSize();
+ if (byte_order == eByteOrderInvalid || address_size == 0)
+ return DWARFExpression(nullptr);
+
+ RegisterKind register_kind = eRegisterKindDWARF;
+ StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
+ switch (symbol.getLocationType()) {
+ case PDB_LocType::Static:
+ case PDB_LocType::TLS: {
+ stream.PutHex8(DW_OP_addr);
+
+ SectionList *section_list = module->GetSectionList();
+ if (!section_list)
+ return DWARFExpression(nullptr);
+
+ uint32_t section_idx = symbol.getAddressSection() - 1;
+ if (section_idx >= section_list->GetSize())
+ return DWARFExpression(nullptr);
+
+ auto section = section_list->GetSectionAtIndex(section_idx);
+ if (!section)
+ return DWARFExpression(nullptr);
+
+ uint32_t offset = symbol.getAddressOffset();
+ stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,
+ byte_order);
+
+ is_constant = false;
+
+ break;
+ }
+ case PDB_LocType::RegRel: {
+ uint32_t reg_num =
+ GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return DWARFExpression(nullptr);
+
+ if (reg_num > 31) {
+ stream.PutHex8(DW_OP_bregx);
+ stream.PutULEB128(reg_num);
+ } else
+ stream.PutHex8(DW_OP_breg0 + reg_num);
+
+ int32_t offset = symbol.getOffset();
+ stream.PutSLEB128(offset);
+
+ is_constant = false;
+
+ break;
+ }
+ case PDB_LocType::Enregistered: {
+ uint32_t reg_num =
+ GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return DWARFExpression(nullptr);
+
+ if (reg_num > 31) {
+ stream.PutHex8(DW_OP_regx);
+ stream.PutULEB128(reg_num);
+ } else
+ stream.PutHex8(DW_OP_reg0 + reg_num);
+
+ is_constant = false;
+
+ break;
+ }
+ case PDB_LocType::Constant: {
+ Variant value = symbol.getValue();
+ stream.PutRawBytes(&value.Value, sizeof(value.Value),
+ endian::InlHostByteOrder());
+ break;
+ }
+ default:
+ return DWARFExpression(nullptr);
+ }
+
+ DataBufferSP buffer =
+ std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
+ DataExtractor extractor(buffer, byte_order, address_size, byte_size);
+ DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize());
+ result.SetRegisterKind(register_kind);
+
+ return result;
+}
diff --git a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
new file mode 100644
index 000000000000..37b80dfccb84
--- /dev/null
+++ b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
@@ -0,0 +1,45 @@
+//===-- PDBLocationToDWARFExpression.h --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_
+#define lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_
+
+#include "lldb/Core/Module.h"
+
+namespace lldb_private {
+class DWARFExpression;
+}
+
+namespace llvm {
+namespace pdb {
+class PDBSymbolData;
+}
+} // namespace llvm
+
+//------------------------------------------------------------------------------
+/// Converts a location information from a PDB symbol to a DWARF expression
+///
+/// @param[in] module
+/// The module \a symbol belongs to.
+///
+/// @param[in] symbol
+/// The symbol with a location information to convert.
+///
+/// @param[out] is_constant
+/// Set to \b true if the result expression is a constant value data,
+/// and \b false if it is a DWARF bytecode.
+///
+/// @return
+/// The DWARF expression corresponding to the location data of \a symbol.
+//------------------------------------------------------------------------------
+lldb_private::DWARFExpression
+ConvertPDBLocationToDWARFExpression(lldb::ModuleSP module,
+ const llvm::pdb::PDBSymbolData &symbol,
+ bool &is_constant);
+#endif
diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index de9b9f024fc7..05f3017819fa 100644
--- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -18,16 +18,21 @@
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Symbol/Variable.h"
#include "lldb/Utility/RegularExpression.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/IPDBDataStream.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
#include "llvm/DebugInfo/PDB/IPDBTable.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
@@ -35,14 +40,18 @@
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
+#include "Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h"
#include <regex>
+using namespace lldb;
using namespace lldb_private;
using namespace llvm::pdb;
@@ -63,7 +72,7 @@ bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
return ((requested_line == 0 || actual_line == requested_line) &&
addr_length > 0);
}
-}
+} // namespace
void SymbolFilePDB::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
@@ -92,7 +101,8 @@ SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
}
SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)
- : SymbolFile(object_file), m_cached_compile_unit_count(0) {}
+ : SymbolFile(object_file), m_session_up(), m_global_scope_up(),
+ m_cached_compile_unit_count(0), m_tu_decl_ctx_up() {}
SymbolFilePDB::~SymbolFilePDB() {}
@@ -116,15 +126,14 @@ uint32_t SymbolFilePDB::CalculateAbilities() {
if (!symfile)
return 0;
error = loadDataForPDB(PDB_ReaderType::DIA,
- llvm::StringRef(symfile.GetPath()),
- m_session_up);
+ llvm::StringRef(symfile.GetPath()), m_session_up);
if (error) {
llvm::consumeError(std::move(error));
return 0;
}
}
}
- if (!m_session_up.get())
+ if (!m_session_up)
return 0;
auto enum_tables_up = m_session_up->getEnumTables();
@@ -138,13 +147,14 @@ uint32_t SymbolFilePDB::CalculateAbilities() {
case PDB_TableType::Symbols:
// This table represents a store of symbols with types listed in
// PDBSym_Type
- abilities |= (CompileUnits | Functions | Blocks |
- GlobalVariables | LocalVariables | VariableTypes);
+ abilities |= (CompileUnits | Functions | Blocks | GlobalVariables |
+ LocalVariables | VariableTypes);
break;
case PDB_TableType::LineNumbers:
abilities |= LineTables;
break;
- default: break;
+ default:
+ break;
}
}
return abilities;
@@ -152,41 +162,88 @@ uint32_t SymbolFilePDB::CalculateAbilities() {
void SymbolFilePDB::InitializeObject() {
lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
+ lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS);
m_session_up->setLoadAddress(obj_load_address);
+ if (!m_global_scope_up)
+ m_global_scope_up = m_session_up->getGlobalScope();
+ lldbassert(m_global_scope_up.get());
TypeSystem *type_system =
GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
ClangASTContext *clang_type_system =
llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ lldbassert(clang_type_system);
m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(
type_system, clang_type_system->GetTranslationUnitDecl());
}
uint32_t SymbolFilePDB::GetNumCompileUnits() {
if (m_cached_compile_unit_count == 0) {
- auto global = m_session_up->getGlobalScope();
- auto compilands = global->findAllChildren<PDBSymbolCompiland>();
+ auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
+ if (!compilands)
+ return 0;
+
+ // The linker could link *.dll (compiland language = LINK), or import
+ // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be
+ // found as a child of the global scope (PDB executable). Usually, such
+ // compilands contain `thunk` symbols in which we are not interested for
+ // now. However we still count them in the compiland list. If we perform
+ // any compiland related activity, like finding symbols through
+ // llvm::pdb::IPDBSession methods, such compilands will all be searched
+ // automatically no matter whether we include them or not.
m_cached_compile_unit_count = compilands->getChildCount();
// The linker can inject an additional "dummy" compilation unit into the
// PDB. Ignore this special compile unit for our purposes, if it is there.
// It is always the last one.
- auto last_cu = compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
- std::string name = last_cu->getName();
+ auto last_compiland_up =
+ compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
+ lldbassert(last_compiland_up.get());
+ std::string name = last_compiland_up->getName();
if (name == "* Linker *")
--m_cached_compile_unit_count;
}
return m_cached_compile_unit_count;
}
-lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
- auto global = m_session_up->getGlobalScope();
- auto compilands = global->findAllChildren<PDBSymbolCompiland>();
- auto cu = compilands->getChildAtIndex(index);
+void SymbolFilePDB::GetCompileUnitIndex(
+ const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index) {
+ auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
+ if (!results_up)
+ return;
+ auto uid = pdb_compiland.getSymIndexId();
+ for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
+ auto compiland_up = results_up->getChildAtIndex(cu_idx);
+ if (!compiland_up)
+ continue;
+ if (compiland_up->getSymIndexId() == uid) {
+ index = cu_idx;
+ return;
+ }
+ }
+ index = UINT32_MAX;
+ return;
+}
- uint32_t id = cu->getSymIndexId();
+std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
+SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) {
+ return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid);
+}
- return ParseCompileUnitForSymIndex(id);
+lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
+ if (index >= GetNumCompileUnits())
+ return CompUnitSP();
+
+ // Assuming we always retrieve same compilands listed in same order through
+ // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a
+ // compile unit makes no sense.
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
+ if (!results)
+ return CompUnitSP();
+ auto compiland_up = results->getChildAtIndex(index);
+ if (!compiland_up)
+ return CompUnitSP();
+ return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index);
}
lldb::LanguageType
@@ -196,24 +253,71 @@ SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) {
if (!sc.comp_unit)
return lldb::eLanguageTypeUnknown;
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
- sc.comp_unit->GetID());
- if (!cu)
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
return lldb::eLanguageTypeUnknown;
- auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
+ auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
if (!details)
return lldb::eLanguageTypeUnknown;
return TranslateLanguage(details->getLanguage());
}
+lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(
+ const PDBSymbolFunc &pdb_func, const lldb_private::SymbolContext &sc) {
+ lldbassert(sc.comp_unit && sc.module_sp.get());
+
+ auto file_vm_addr = pdb_func.getVirtualAddress();
+ if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+ return nullptr;
+
+ auto func_length = pdb_func.getLength();
+ AddressRange func_range =
+ AddressRange(file_vm_addr, func_length, sc.module_sp->GetSectionList());
+ if (!func_range.GetBaseAddress().IsValid())
+ return nullptr;
+
+ lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId());
+ if (!func_type)
+ return nullptr;
+
+ user_id_t func_type_uid = pdb_func.getSignatureId();
+
+ Mangled mangled = GetMangledForPDBFunc(pdb_func);
+
+ FunctionSP func_sp =
+ std::make_shared<Function>(sc.comp_unit, pdb_func.getSymIndexId(),
+ func_type_uid, mangled, func_type, func_range);
+
+ sc.comp_unit->AddFunction(func_sp);
+ return func_sp.get();
+}
+
size_t SymbolFilePDB::ParseCompileUnitFunctions(
const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ lldbassert(sc.comp_unit);
+ size_t func_added = 0;
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
+ return 0;
+ auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>();
+ if (!results_up)
+ return 0;
+ while (auto pdb_func_up = results_up->getNext()) {
+ auto func_sp =
+ sc.comp_unit->FindFunctionByUID(pdb_func_up->getSymIndexId());
+ if (!func_sp) {
+ if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, sc))
+ ++func_added;
+ }
+ }
+ return func_added;
}
bool SymbolFilePDB::ParseCompileUnitLineTable(
const lldb_private::SymbolContext &sc) {
+ lldbassert(sc.comp_unit);
+ if (sc.comp_unit->GetLineTable())
+ return true;
return ParseCompileUnitLineTable(sc, 0);
}
@@ -226,26 +330,29 @@ bool SymbolFilePDB::ParseCompileUnitDebugMacros(
bool SymbolFilePDB::ParseCompileUnitSupportFiles(
const lldb_private::SymbolContext &sc,
lldb_private::FileSpecList &support_files) {
- if (!sc.comp_unit)
- return false;
+ lldbassert(sc.comp_unit);
// In theory this is unnecessary work for us, because all of this information
// is easily (and quickly) accessible from DebugInfoPDB, so caching it a
// second time seems like a waste. Unfortunately, there's no good way around
// this short of a moderate refactor since SymbolVendor depends on being able
// to cache this list.
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
- sc.comp_unit->GetID());
- if (!cu)
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
return false;
- auto files = m_session_up->getSourceFilesForCompiland(*cu);
+ auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
if (!files || files->getChildCount() == 0)
return false;
while (auto file = files->getNext()) {
- FileSpec spec(file->getFileName(), false);
- support_files.Append(spec);
+ FileSpec spec(file->getFileName(), false, FileSpec::Style::windows);
+ support_files.AppendIfUnique(spec);
}
+
+ // LLDB uses the DWARF-like file numeration (one based),
+ // the zeroth file is the compile unit itself
+ support_files.Insert(0, *sc.comp_unit);
+
return true;
}
@@ -256,21 +363,178 @@ bool SymbolFilePDB::ParseImportedModules(
return false;
}
+static size_t ParseFunctionBlocksForPDBSymbol(
+ const lldb_private::SymbolContext &sc, uint64_t func_file_vm_addr,
+ const llvm::pdb::PDBSymbol *pdb_symbol, lldb_private::Block *parent_block,
+ bool is_top_parent) {
+ assert(pdb_symbol && parent_block);
+
+ size_t num_added = 0;
+ switch (pdb_symbol->getSymTag()) {
+ case PDB_SymType::Block:
+ case PDB_SymType::Function: {
+ Block *block = nullptr;
+ auto &raw_sym = pdb_symbol->getRawSymbol();
+ if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) {
+ if (pdb_func->hasNoInlineAttribute())
+ break;
+ if (is_top_parent)
+ block = parent_block;
+ else
+ break;
+ } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) {
+ auto uid = pdb_symbol->getSymIndexId();
+ if (parent_block->FindBlockByID(uid))
+ break;
+ if (raw_sym.getVirtualAddress() < func_file_vm_addr)
+ break;
+
+ auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId());
+ parent_block->AddChild(block_sp);
+ block = block_sp.get();
+ } else
+ llvm_unreachable("Unexpected PDB symbol!");
+
+ block->AddRange(Block::Range(
+ raw_sym.getVirtualAddress() - func_file_vm_addr, raw_sym.getLength()));
+ block->FinalizeRanges();
+ ++num_added;
+
+ auto results_up = pdb_symbol->findAllChildren();
+ if (!results_up)
+ break;
+ while (auto symbol_up = results_up->getNext()) {
+ num_added += ParseFunctionBlocksForPDBSymbol(
+ sc, func_file_vm_addr, symbol_up.get(), block, false);
+ }
+ } break;
+ default:
+ break;
+ }
+ return num_added;
+}
+
size_t
SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ lldbassert(sc.comp_unit && sc.function);
+ size_t num_added = 0;
+ auto uid = sc.function->GetID();
+ auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
+ if (!pdb_func_up)
+ return 0;
+ Block &parent_block = sc.function->GetBlock(false);
+ num_added =
+ ParseFunctionBlocksForPDBSymbol(sc, pdb_func_up->getVirtualAddress(),
+ pdb_func_up.get(), &parent_block, true);
+ return num_added;
}
size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ lldbassert(sc.module_sp.get());
+ if (!sc.comp_unit)
+ return 0;
+
+ size_t num_added = 0;
+ auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland)
+ return 0;
+
+ auto ParseTypesByTagFn = [&num_added, this](const PDBSymbol &raw_sym) {
+ std::unique_ptr<IPDBEnumSymbols> results;
+ PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
+ PDB_SymType::UDT};
+ for (auto tag : tags_to_search) {
+ results = raw_sym.findAllChildren(tag);
+ if (!results || results->getChildCount() == 0)
+ continue;
+ while (auto symbol = results->getNext()) {
+ switch (symbol->getSymTag()) {
+ case PDB_SymType::Enum:
+ case PDB_SymType::UDT:
+ case PDB_SymType::Typedef:
+ break;
+ default:
+ continue;
+ }
+
+ // This should cause the type to get cached and stored in the `m_types`
+ // lookup.
+ if (!ResolveTypeUID(symbol->getSymIndexId()))
+ continue;
+
+ ++num_added;
+ }
+ }
+ };
+
+ if (sc.function) {
+ auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
+ sc.function->GetID());
+ if (!pdb_func)
+ return 0;
+ ParseTypesByTagFn(*pdb_func);
+ } else {
+ ParseTypesByTagFn(*compiland);
+
+ // Also parse global types particularly coming from this compiland.
+ // Unfortunately, PDB has no compiland information for each global type. We
+ // have to parse them all. But ensure we only do this once.
+ static bool parse_all_global_types = false;
+ if (!parse_all_global_types) {
+ ParseTypesByTagFn(*m_global_scope_up);
+ parse_all_global_types = true;
+ }
+ }
+ return num_added;
}
size_t
SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
- // TODO: Implement this
- return size_t();
+ if (!sc.comp_unit)
+ return 0;
+
+ size_t num_added = 0;
+ if (sc.function) {
+ auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
+ sc.function->GetID());
+ if (!pdb_func)
+ return 0;
+
+ num_added += ParseVariables(sc, *pdb_func);
+ sc.function->GetBlock(false).SetDidParseVariables(true, true);
+ } else if (sc.comp_unit) {
+ auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland)
+ return 0;
+
+ if (sc.comp_unit->GetVariableList(false))
+ return 0;
+
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
+ if (results && results->getChildCount()) {
+ while (auto result = results->getNext()) {
+ auto cu_id = result->getCompilandId();
+ // FIXME: We are not able to determine variable's compile unit.
+ if (cu_id == 0)
+ continue;
+
+ if (cu_id == sc.comp_unit->GetID())
+ num_added += ParseVariables(sc, *result);
+ }
+ }
+
+ // FIXME: A `file static` or `global constant` variable appears both in
+ // compiland's children and global scope's children with unexpectedly
+ // different symbol's Id making it ambiguous.
+
+ // FIXME: 'local constant', for example, const char var[] = "abc", declared
+ // in a function scope, can't be found in PDB.
+
+ // Parse variables in this compiland.
+ num_added += ParseVariables(sc, *compiland);
+ }
+
+ return num_added;
}
lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
@@ -294,8 +558,12 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
return nullptr;
lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
- if (result.get())
+ if (result) {
m_types.insert(std::make_pair(type_uid, result));
+ auto type_list = GetTypeList();
+ if (type_list)
+ type_list->Insert(result);
+ }
return result.get();
}
@@ -328,12 +596,62 @@ uint32_t
SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
uint32_t resolve_scope,
lldb_private::SymbolContext &sc) {
- return uint32_t();
+ uint32_t resolved_flags = 0;
+ if (resolve_scope & eSymbolContextCompUnit ||
+ resolve_scope & eSymbolContextVariable ||
+ resolve_scope & eSymbolContextFunction ||
+ resolve_scope & eSymbolContextBlock ||
+ resolve_scope & eSymbolContextLineEntry) {
+ auto cu_sp = GetCompileUnitContainsAddress(so_addr);
+ if (!cu_sp) {
+ if (resolved_flags | eSymbolContextVariable) {
+ // TODO: Resolve variables
+ }
+ return 0;
+ }
+ sc.comp_unit = cu_sp.get();
+ resolved_flags |= eSymbolContextCompUnit;
+ lldbassert(sc.module_sp == cu_sp->GetModule());
+ }
+
+ if (resolve_scope & eSymbolContextFunction) {
+ addr_t file_vm_addr = so_addr.GetFileAddress();
+ auto symbol_up =
+ m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function);
+ if (symbol_up) {
+ auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
+ assert(pdb_func);
+ auto func_uid = pdb_func->getSymIndexId();
+ sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
+ if (sc.function == nullptr)
+ sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
+ if (sc.function) {
+ resolved_flags |= eSymbolContextFunction;
+ if (resolve_scope & eSymbolContextBlock) {
+ Block &block = sc.function->GetBlock(true);
+ sc.block = block.FindBlockByID(sc.function->GetID());
+ if (sc.block)
+ resolved_flags |= eSymbolContextBlock;
+ }
+ }
+ }
+ }
+
+ if (resolve_scope & eSymbolContextLineEntry) {
+ if (auto *line_table = sc.comp_unit->GetLineTable()) {
+ Address addr(so_addr);
+ if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
+ resolved_flags |= eSymbolContextLineEntry;
+ }
+ }
+
+ return resolved_flags;
}
uint32_t SymbolFilePDB::ResolveSymbolContext(
const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) {
+ const size_t old_size = sc_list.GetSize();
if (resolve_scope & lldb::eSymbolContextCompUnit) {
// Locate all compilation units with line numbers referencing the specified
// file. For example, if `file_spec` is <vector>, then this should return
@@ -342,56 +660,498 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(
auto compilands = m_session_up->findCompilandsForSourceFile(
file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive);
+ if (!compilands)
+ return 0;
+
// For each one, either find its previously parsed data or parse it afresh
// and add it to the symbol context list.
while (auto compiland = compilands->getNext()) {
- // If we're not checking inlines, then don't add line information for this
- // file unless the FileSpec matches.
+ // If we're not checking inlines, then don't add line information for
+ // this file unless the FileSpec matches. For inline functions, we don't
+ // have to match the FileSpec since they could be defined in headers
+ // other than file specified in FileSpec.
if (!check_inlines) {
- // `getSourceFileName` returns the basename of the original source file
- // used to generate this compiland. It does not return the full path.
- // Currently the only way to get that is to do a basename lookup to get
- // the IPDBSourceFile, but this is ambiguous in the case of two source
- // files with the same name contributing to the same compiland. This is
- // a moderately extreme edge case, so we consider this OK for now,
- // although we need to find a long-term solution.
- std::string source_file = compiland->getSourceFileName();
- auto pdb_file = m_session_up->findOneSourceFile(
- compiland.get(), source_file,
- PDB_NameSearchFlags::NS_CaseInsensitive);
- source_file = pdb_file->getFileName();
- FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows);
- if (!file_spec.FileEquals(this_spec))
+ std::string source_file = compiland->getSourceFileFullPath();
+ if (source_file.empty())
+ continue;
+ FileSpec this_spec(source_file, false, FileSpec::Style::windows);
+ bool need_full_match = !file_spec.GetDirectory().IsEmpty();
+ if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0)
continue;
}
SymbolContext sc;
- auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId());
+ auto cu = ParseCompileUnitForUID(compiland->getSymIndexId());
+ if (!cu)
+ continue;
sc.comp_unit = cu.get();
sc.module_sp = cu->GetModule();
- sc_list.Append(sc);
// If we were asked to resolve line entries, add all entries to the line
// table that match the requested line (or all lines if `line` == 0).
- if (resolve_scope & lldb::eSymbolContextLineEntry)
- ParseCompileUnitLineTable(sc, line);
+ if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock |
+ eSymbolContextLineEntry)) {
+ bool has_line_table = ParseCompileUnitLineTable(sc, line);
+
+ if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) {
+ // The query asks for line entries, but we can't get them for the
+ // compile unit. This is not normal for `line` = 0. So just assert
+ // it.
+ assert(line && "Couldn't get all line entries!\n");
+
+ // Current compiland does not have the requested line. Search next.
+ continue;
+ }
+
+ if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
+ if (!has_line_table)
+ continue;
+
+ auto *line_table = sc.comp_unit->GetLineTable();
+ lldbassert(line_table);
+
+ uint32_t num_line_entries = line_table->GetSize();
+ // Skip the terminal line entry.
+ --num_line_entries;
+
+ // If `line `!= 0, see if we can resolve function for each line entry
+ // in the line table.
+ for (uint32_t line_idx = 0; line && line_idx < num_line_entries;
+ ++line_idx) {
+ if (!line_table->GetLineEntryAtIndex(line_idx, sc.line_entry))
+ continue;
+
+ auto file_vm_addr =
+ sc.line_entry.range.GetBaseAddress().GetFileAddress();
+ if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+ continue;
+
+ auto symbol_up = m_session_up->findSymbolByAddress(
+ file_vm_addr, PDB_SymType::Function);
+ if (symbol_up) {
+ auto func_uid = symbol_up->getSymIndexId();
+ sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
+ if (sc.function == nullptr) {
+ auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
+ assert(pdb_func);
+ sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
+ }
+ if (sc.function && (resolve_scope & eSymbolContextBlock)) {
+ Block &block = sc.function->GetBlock(true);
+ sc.block = block.FindBlockByID(sc.function->GetID());
+ }
+ }
+ sc_list.Append(sc);
+ }
+ } else if (has_line_table) {
+ // We can parse line table for the compile unit. But no query to
+ // resolve function or block. We append `sc` to the list anyway.
+ sc_list.Append(sc);
+ }
+ } else {
+ // No query for line entry, function or block. But we have a valid
+ // compile unit, append `sc` to the list.
+ sc_list.Append(sc);
+ }
}
}
- return sc_list.GetSize();
+ return sc_list.GetSize() - old_size;
+}
+
+std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) {
+ std::string decorated_name;
+ auto vm_addr = pdb_data.getVirtualAddress();
+ if (vm_addr != LLDB_INVALID_ADDRESS && vm_addr) {
+ auto result_up =
+ m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol);
+ if (result_up) {
+ while (auto symbol_up = result_up->getNext()) {
+ if (symbol_up->getRawSymbol().getVirtualAddress() == vm_addr) {
+ decorated_name = symbol_up->getRawSymbol().getName();
+ break;
+ }
+ }
+ }
+ }
+ if (!decorated_name.empty())
+ return decorated_name;
+
+ return std::string();
+}
+
+VariableSP SymbolFilePDB::ParseVariableForPDBData(
+ const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbolData &pdb_data) {
+ VariableSP var_sp;
+ uint32_t var_uid = pdb_data.getSymIndexId();
+ auto result = m_variables.find(var_uid);
+ if (result != m_variables.end())
+ return result->second;
+
+ ValueType scope = eValueTypeInvalid;
+ bool is_static_member = false;
+ bool is_external = false;
+ bool is_artificial = false;
+
+ switch (pdb_data.getDataKind()) {
+ case PDB_DataKind::Global:
+ scope = eValueTypeVariableGlobal;
+ is_external = true;
+ break;
+ case PDB_DataKind::Local:
+ scope = eValueTypeVariableLocal;
+ break;
+ case PDB_DataKind::FileStatic:
+ scope = eValueTypeVariableStatic;
+ break;
+ case PDB_DataKind::StaticMember:
+ is_static_member = true;
+ scope = eValueTypeVariableStatic;
+ break;
+ case PDB_DataKind::Member:
+ scope = eValueTypeVariableStatic;
+ break;
+ case PDB_DataKind::Param:
+ scope = eValueTypeVariableArgument;
+ break;
+ case PDB_DataKind::Constant:
+ scope = eValueTypeConstResult;
+ break;
+ default:
+ break;
+ }
+
+ switch (pdb_data.getLocationType()) {
+ case PDB_LocType::TLS:
+ scope = eValueTypeVariableThreadLocal;
+ break;
+ case PDB_LocType::RegRel: {
+ // It is a `this` pointer.
+ if (pdb_data.getDataKind() == PDB_DataKind::ObjectPtr) {
+ scope = eValueTypeVariableArgument;
+ is_artificial = true;
+ }
+ } break;
+ default:
+ break;
+ }
+
+ Declaration decl;
+ if (!is_artificial && !pdb_data.isCompilerGenerated()) {
+ if (auto lines = pdb_data.getLineNumbers()) {
+ if (auto first_line = lines->getNext()) {
+ uint32_t src_file_id = first_line->getSourceFileId();
+ auto src_file = m_session_up->getSourceFileById(src_file_id);
+ if (src_file) {
+ FileSpec spec(src_file->getFileName(), /*resolve_path*/ false);
+ decl.SetFile(spec);
+ decl.SetColumn(first_line->getColumnNumber());
+ decl.SetLine(first_line->getLineNumber());
+ }
+ }
+ }
+ }
+
+ Variable::RangeList ranges;
+ SymbolContextScope *context_scope = sc.comp_unit;
+ if (scope == eValueTypeVariableLocal) {
+ if (sc.function) {
+ context_scope = sc.function->GetBlock(true).FindBlockByID(
+ pdb_data.getClassParentId());
+ if (context_scope == nullptr)
+ context_scope = sc.function;
+ }
+ }
+
+ SymbolFileTypeSP type_sp =
+ std::make_shared<SymbolFileType>(*this, pdb_data.getTypeId());
+
+ auto var_name = pdb_data.getName();
+ auto mangled = GetMangledForPDBData(pdb_data);
+ auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
+
+ bool is_constant;
+ DWARFExpression location = ConvertPDBLocationToDWARFExpression(
+ GetObjectFile()->GetModule(), pdb_data, is_constant);
+
+ var_sp = std::make_shared<Variable>(
+ var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
+ ranges, &decl, location, is_external, is_artificial, is_static_member);
+ var_sp->SetLocationIsConstantValueData(is_constant);
+
+ m_variables.insert(std::make_pair(var_uid, var_sp));
+ return var_sp;
+}
+
+size_t
+SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbol &pdb_symbol,
+ lldb_private::VariableList *variable_list) {
+ size_t num_added = 0;
+
+ if (auto pdb_data = llvm::dyn_cast<PDBSymbolData>(&pdb_symbol)) {
+ VariableListSP local_variable_list_sp;
+
+ auto result = m_variables.find(pdb_data->getSymIndexId());
+ if (result != m_variables.end()) {
+ if (variable_list)
+ variable_list->AddVariableIfUnique(result->second);
+ } else {
+ // Prepare right VariableList for this variable.
+ if (auto lexical_parent = pdb_data->getLexicalParent()) {
+ switch (lexical_parent->getSymTag()) {
+ case PDB_SymType::Exe:
+ assert(sc.comp_unit);
+ LLVM_FALLTHROUGH;
+ case PDB_SymType::Compiland: {
+ if (sc.comp_unit) {
+ local_variable_list_sp = sc.comp_unit->GetVariableList(false);
+ if (!local_variable_list_sp) {
+ local_variable_list_sp = std::make_shared<VariableList>();
+ sc.comp_unit->SetVariableList(local_variable_list_sp);
+ }
+ }
+ } break;
+ case PDB_SymType::Block:
+ case PDB_SymType::Function: {
+ if (sc.function) {
+ Block *block = sc.function->GetBlock(true).FindBlockByID(
+ lexical_parent->getSymIndexId());
+ if (block) {
+ local_variable_list_sp = block->GetBlockVariableList(false);
+ if (!local_variable_list_sp) {
+ local_variable_list_sp = std::make_shared<VariableList>();
+ block->SetVariableList(local_variable_list_sp);
+ }
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+
+ if (local_variable_list_sp) {
+ if (auto var_sp = ParseVariableForPDBData(sc, *pdb_data)) {
+ local_variable_list_sp->AddVariableIfUnique(var_sp);
+ if (variable_list)
+ variable_list->AddVariableIfUnique(var_sp);
+ ++num_added;
+ }
+ }
+ }
+ }
+
+ if (auto results = pdb_symbol.findAllChildren()) {
+ while (auto result = results->getNext())
+ num_added += ParseVariables(sc, *result, variable_list);
+ }
+
+ return num_added;
}
uint32_t SymbolFilePDB::FindGlobalVariables(
const lldb_private::ConstString &name,
- const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
uint32_t max_matches, lldb_private::VariableList &variables) {
- return uint32_t();
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return 0;
+ if (name.IsEmpty())
+ return 0;
+
+ auto results =
+ m_global_scope_up->findChildren(PDB_SymType::Data, name.GetStringRef(),
+ PDB_NameSearchFlags::NS_CaseSensitive);
+ if (!results)
+ return 0;
+
+ uint32_t matches = 0;
+ size_t old_size = variables.GetSize();
+ while (auto result = results->getNext()) {
+ auto pdb_data = llvm::dyn_cast<PDBSymbolData>(result.get());
+ if (max_matches > 0 && matches >= max_matches)
+ break;
+
+ SymbolContext sc;
+ sc.module_sp = m_obj_file->GetModule();
+ lldbassert(sc.module_sp.get());
+
+ sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+ // FIXME: We are not able to determine the compile unit.
+ if (sc.comp_unit == nullptr)
+ continue;
+
+ ParseVariables(sc, *pdb_data, &variables);
+ matches = variables.GetSize() - old_size;
+ }
+
+ return matches;
}
uint32_t
SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) {
- return uint32_t();
+ if (!regex.IsValid())
+ return 0;
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
+ if (!results)
+ return 0;
+
+ uint32_t matches = 0;
+ size_t old_size = variables.GetSize();
+ while (auto pdb_data = results->getNext()) {
+ if (max_matches > 0 && matches >= max_matches)
+ break;
+
+ auto var_name = pdb_data->getName();
+ if (var_name.empty())
+ continue;
+ if (!regex.Execute(var_name))
+ continue;
+ SymbolContext sc;
+ sc.module_sp = m_obj_file->GetModule();
+ lldbassert(sc.module_sp.get());
+
+ sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+ // FIXME: We are not able to determine the compile unit.
+ if (sc.comp_unit == nullptr)
+ continue;
+
+ ParseVariables(sc, *pdb_data, &variables);
+ matches = variables.GetSize() - old_size;
+ }
+
+ return matches;
+}
+
+bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) {
+ lldb_private::SymbolContext sc;
+ sc.comp_unit = ParseCompileUnitForUID(pdb_func.getCompilandId()).get();
+ if (!sc.comp_unit)
+ return false;
+ sc.module_sp = sc.comp_unit->GetModule();
+ sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc);
+ if (!sc.function)
+ return false;
+
+ sc_list.Append(sc);
+ return true;
+}
+
+bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines,
+ lldb_private::SymbolContextList &sc_list) {
+ auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
+ if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute()))
+ return false;
+ return ResolveFunction(*pdb_func_up, include_inlines, sc_list);
+}
+
+void SymbolFilePDB::CacheFunctionNames() {
+ if (!m_func_full_names.IsEmpty())
+ return;
+
+ std::map<uint64_t, uint32_t> addr_ids;
+
+ if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) {
+ while (auto pdb_func_up = results_up->getNext()) {
+ if (pdb_func_up->isCompilerGenerated())
+ continue;
+
+ auto name = pdb_func_up->getName();
+ auto demangled_name = pdb_func_up->getUndecoratedName();
+ if (name.empty() && demangled_name.empty())
+ continue;
+
+ auto uid = pdb_func_up->getSymIndexId();
+ if (!demangled_name.empty() && pdb_func_up->getVirtualAddress())
+ addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid));
+
+ if (auto parent = pdb_func_up->getClassParent()) {
+
+ // PDB have symbols for class/struct methods or static methods in Enum
+ // Class. We won't bother to check if the parent is UDT or Enum here.
+ m_func_method_names.Append(ConstString(name), uid);
+
+ ConstString cstr_name(name);
+
+ // To search a method name, like NS::Class:MemberFunc, LLDB searches
+ // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does
+ // not have inforamtion of this, we extract base names and cache them
+ // by our own effort.
+ llvm::StringRef basename;
+ CPlusPlusLanguage::MethodName cpp_method(cstr_name);
+ if (cpp_method.IsValid()) {
+ llvm::StringRef context;
+ basename = cpp_method.GetBasename();
+ if (basename.empty())
+ CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(),
+ context, basename);
+ }
+
+ if (!basename.empty())
+ m_func_base_names.Append(ConstString(basename), uid);
+ else {
+ m_func_base_names.Append(ConstString(name), uid);
+ }
+
+ if (!demangled_name.empty())
+ m_func_full_names.Append(ConstString(demangled_name), uid);
+
+ } else {
+ // Handle not-method symbols.
+
+ // The function name might contain namespace, or its lexical scope. It
+ // is not safe to get its base name by applying same scheme as we deal
+ // with the method names.
+ // FIXME: Remove namespace if function is static in a scope.
+ m_func_base_names.Append(ConstString(name), uid);
+
+ if (name == "main") {
+ m_func_full_names.Append(ConstString(name), uid);
+
+ if (!demangled_name.empty() && name != demangled_name) {
+ m_func_full_names.Append(ConstString(demangled_name), uid);
+ m_func_base_names.Append(ConstString(demangled_name), uid);
+ }
+ } else if (!demangled_name.empty()) {
+ m_func_full_names.Append(ConstString(demangled_name), uid);
+ } else {
+ m_func_full_names.Append(ConstString(name), uid);
+ }
+ }
+ }
+ }
+
+ if (auto results_up =
+ m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) {
+ while (auto pub_sym_up = results_up->getNext()) {
+ if (!pub_sym_up->isFunction())
+ continue;
+ auto name = pub_sym_up->getName();
+ if (name.empty())
+ continue;
+
+ if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) {
+ auto vm_addr = pub_sym_up->getVirtualAddress();
+
+ // PDB public symbol has mangled name for its associated function.
+ if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) {
+ // Cache mangled name.
+ m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]);
+ }
+ }
+ }
+ }
+ // Sort them before value searching is working properly
+ m_func_full_names.Sort();
+ m_func_full_names.SizeToFit();
+ m_func_method_names.Sort();
+ m_func_method_names.SizeToFit();
+ m_func_base_names.Sort();
+ m_func_base_names.SizeToFit();
}
uint32_t SymbolFilePDB::FindFunctions(
@@ -399,14 +1159,77 @@ uint32_t SymbolFilePDB::FindFunctions(
const lldb_private::CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask, bool include_inlines, bool append,
lldb_private::SymbolContextList &sc_list) {
- return uint32_t();
+ if (!append)
+ sc_list.Clear();
+ lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0);
+
+ if (name_type_mask == eFunctionNameTypeNone)
+ return 0;
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return 0;
+ if (name.IsEmpty())
+ return 0;
+
+ auto old_size = sc_list.GetSize();
+ if (name_type_mask & eFunctionNameTypeFull ||
+ name_type_mask & eFunctionNameTypeBase ||
+ name_type_mask & eFunctionNameTypeMethod) {
+ CacheFunctionNames();
+
+ std::set<uint32_t> resolved_ids;
+ auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids,
+ this](UniqueCStringMap<uint32_t> &Names) {
+ std::vector<uint32_t> ids;
+ if (Names.GetValues(name, ids)) {
+ for (auto id : ids) {
+ if (resolved_ids.find(id) == resolved_ids.end()) {
+ if (ResolveFunction(id, include_inlines, sc_list))
+ resolved_ids.insert(id);
+ }
+ }
+ }
+ };
+ if (name_type_mask & eFunctionNameTypeFull) {
+ ResolveFn(m_func_full_names);
+ }
+ if (name_type_mask & eFunctionNameTypeBase) {
+ ResolveFn(m_func_base_names);
+ }
+ if (name_type_mask & eFunctionNameTypeMethod) {
+ ResolveFn(m_func_method_names);
+ }
+ }
+ return sc_list.GetSize() - old_size;
}
uint32_t
SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex,
bool include_inlines, bool append,
lldb_private::SymbolContextList &sc_list) {
- return uint32_t();
+ if (!append)
+ sc_list.Clear();
+ if (!regex.IsValid())
+ return 0;
+
+ auto old_size = sc_list.GetSize();
+ CacheFunctionNames();
+
+ std::set<uint32_t> resolved_ids;
+ auto ResolveFn = [&regex, include_inlines, &sc_list, &resolved_ids,
+ this](UniqueCStringMap<uint32_t> &Names) {
+ std::vector<uint32_t> ids;
+ if (Names.GetValues(regex, ids)) {
+ for (auto id : ids) {
+ if (resolved_ids.find(id) == resolved_ids.end())
+ if (ResolveFunction(id, include_inlines, sc_list))
+ resolved_ids.insert(id);
+ }
+ }
+ };
+ ResolveFn(m_func_full_names);
+ ResolveFn(m_func_base_names);
+
+ return sc_list.GetSize() - old_size;
}
void SymbolFilePDB::GetMangledNamesForFunction(
@@ -424,6 +1247,8 @@ uint32_t SymbolFilePDB::FindTypes(
types.Clear();
if (!name)
return 0;
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return 0;
searched_symbol_files.clear();
searched_symbol_files.insert(this);
@@ -432,14 +1257,13 @@ uint32_t SymbolFilePDB::FindTypes(
// There is an assumption 'name' is not a regex
FindTypesByName(name_str, max_matches, types);
-
+
return types.GetSize();
}
-void
-SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression &regex,
- uint32_t max_matches,
- lldb_private::TypeMap &types) {
+void SymbolFilePDB::FindTypesByRegex(
+ const lldb_private::RegularExpression &regex, uint32_t max_matches,
+ lldb_private::TypeMap &types) {
// When searching by regex, we need to go out of our way to limit the search
// space as much as possible since this searches EVERYTHING in the PDB,
// manually doing regex comparisons. PDB library isn't optimized for regex
@@ -448,13 +1272,15 @@ SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression &regex,
// and do a regex comparison against each of them.
PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
PDB_SymType::UDT};
- auto global = m_session_up->getGlobalScope();
std::unique_ptr<IPDBEnumSymbols> results;
uint32_t matches = 0;
for (auto tag : tags_to_search) {
- results = global->findAllChildren(tag);
+ results = m_global_scope_up->findAllChildren(tag);
+ if (!results)
+ continue;
+
while (auto result = results->getNext()) {
if (max_matches > 0 && matches >= max_matches)
break;
@@ -493,10 +1319,13 @@ SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression &regex,
void SymbolFilePDB::FindTypesByName(const std::string &name,
uint32_t max_matches,
lldb_private::TypeMap &types) {
- auto global = m_session_up->getGlobalScope();
std::unique_ptr<IPDBEnumSymbols> results;
- results = global->findChildren(PDB_SymType::None, name,
- PDB_NameSearchFlags::NS_Default);
+ if (name.empty())
+ return;
+ results = m_global_scope_up->findChildren(PDB_SymType::None, name,
+ PDB_NameSearchFlags::NS_Default);
+ if (!results)
+ return;
uint32_t matches = 0;
@@ -509,8 +1338,8 @@ void SymbolFilePDB::FindTypesByName(const std::string &name,
case PDB_SymType::Typedef:
break;
default:
- // We're looking only for types that have names. Skip symbols, as well as
- // unnamed types such as arrays, pointers, etc.
+ // We're looking only for types that have names. Skip symbols, as well
+ // as unnamed types such as arrays, pointers, etc.
continue;
}
@@ -533,12 +1362,87 @@ size_t SymbolFilePDB::FindTypes(
return 0;
}
-lldb_private::TypeList *SymbolFilePDB::GetTypeList() { return nullptr; }
+lldb_private::TypeList *SymbolFilePDB::GetTypeList() {
+ return m_obj_file->GetModule()->GetTypeList();
+}
+
+void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
+ uint32_t type_mask,
+ TypeCollection &type_collection) {
+ bool can_parse = false;
+ switch (pdb_symbol.getSymTag()) {
+ case PDB_SymType::ArrayType:
+ can_parse = ((type_mask & eTypeClassArray) != 0);
+ break;
+ case PDB_SymType::BuiltinType:
+ can_parse = ((type_mask & eTypeClassBuiltin) != 0);
+ break;
+ case PDB_SymType::Enum:
+ can_parse = ((type_mask & eTypeClassEnumeration) != 0);
+ break;
+ case PDB_SymType::Function:
+ case PDB_SymType::FunctionSig:
+ can_parse = ((type_mask & eTypeClassFunction) != 0);
+ break;
+ case PDB_SymType::PointerType:
+ can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer |
+ eTypeClassMemberPointer)) != 0);
+ break;
+ case PDB_SymType::Typedef:
+ can_parse = ((type_mask & eTypeClassTypedef) != 0);
+ break;
+ case PDB_SymType::UDT: {
+ auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&pdb_symbol);
+ assert(udt);
+ can_parse = (udt->getUdtKind() != PDB_UdtType::Interface &&
+ ((type_mask & (eTypeClassClass | eTypeClassStruct |
+ eTypeClassUnion)) != 0));
+ } break;
+ default:
+ break;
+ }
+
+ if (can_parse) {
+ if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) {
+ auto result =
+ std::find(type_collection.begin(), type_collection.end(), type);
+ if (result == type_collection.end())
+ type_collection.push_back(type);
+ }
+ }
+
+ auto results_up = pdb_symbol.findAllChildren();
+ while (auto symbol_up = results_up->getNext())
+ GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection);
+}
size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
uint32_t type_mask,
lldb_private::TypeList &type_list) {
- return size_t();
+ TypeCollection type_collection;
+ uint32_t old_size = type_list.GetSize();
+ CompileUnit *cu =
+ sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr;
+ if (cu) {
+ auto compiland_up = GetPDBCompilandByUID(cu->GetID());
+ if (!compiland_up)
+ return 0;
+ GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
+ } else {
+ for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
+ auto cu_sp = ParseCompileUnitAtIndex(cu_idx);
+ if (cu_sp) {
+ if (auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID()))
+ GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
+ }
+ }
+ }
+
+ for (auto type : type_collection) {
+ type->GetForwardCompilerType();
+ type_list.Insert(type->shared_from_this());
+ }
+ return type_list.GetSize() - old_size;
}
lldb_private::TypeSystem *
@@ -570,65 +1474,78 @@ const IPDBSession &SymbolFilePDB::GetPDBSession() const {
return *m_session_up;
}
-lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id) {
+lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id,
+ uint32_t index) {
auto found_cu = m_comp_units.find(id);
if (found_cu != m_comp_units.end())
return found_cu->second;
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(id);
-
- // `getSourceFileName` returns the basename of the original source file used
- // to generate this compiland. It does not return the full path. Currently
- // the only way to get that is to do a basename lookup to get the
- // IPDBSourceFile, but this is ambiguous in the case of two source files with
- // the same name contributing to the same compiland. This is a moderately
- // extreme edge case, so we consider this OK for now, although we need to find
- // a long-term solution.
- auto file =
- m_session_up->findOneSourceFile(cu.get(), cu->getSourceFileName(),
- PDB_NameSearchFlags::NS_CaseInsensitive);
- std::string path = file->getFileName();
+ auto compiland_up = GetPDBCompilandByUID(id);
+ if (!compiland_up)
+ return CompUnitSP();
lldb::LanguageType lang;
- auto details = cu->findOneChild<PDBSymbolCompilandDetails>();
+ auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
if (!details)
lang = lldb::eLanguageTypeC_plus_plus;
else
lang = TranslateLanguage(details->getLanguage());
+ if (lang == lldb::LanguageType::eLanguageTypeUnknown)
+ return CompUnitSP();
+
+ std::string path = compiland_up->getSourceFileFullPath();
+ if (path.empty())
+ return CompUnitSP();
+
// Don't support optimized code for now, DebugInfoPDB does not return this
// information.
LazyBool optimized = eLazyBoolNo;
- auto result = std::make_shared<CompileUnit>(
- m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized);
- m_comp_units.insert(std::make_pair(id, result));
- return result;
+ auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr,
+ path.c_str(), id, lang, optimized);
+
+ if (!cu_sp)
+ return CompUnitSP();
+
+ m_comp_units.insert(std::make_pair(id, cu_sp));
+ if (index == UINT32_MAX)
+ GetCompileUnitIndex(*compiland_up, index);
+ lldbassert(index != UINT32_MAX);
+ m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(index,
+ cu_sp);
+ return cu_sp;
}
bool SymbolFilePDB::ParseCompileUnitLineTable(
const lldb_private::SymbolContext &sc, uint32_t match_line) {
- auto global = m_session_up->getGlobalScope();
- auto cu = m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(
- sc.comp_unit->GetID());
+ lldbassert(sc.comp_unit);
+
+ auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ if (!compiland_up)
+ return false;
// LineEntry needs the *index* of the file into the list of support files
// returned by ParseCompileUnitSupportFiles. But the underlying SDK gives us
- // a globally unique idenfitifier in the namespace of the PDB. So, we have to
- // do a mapping so that we can hand out indices.
+ // a globally unique idenfitifier in the namespace of the PDB. So, we have
+ // to do a mapping so that we can hand out indices.
llvm::DenseMap<uint32_t, uint32_t> index_map;
- BuildSupportFileIdToSupportFileIndexMap(*cu, index_map);
+ BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map);
auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
- // Find contributions to `cu` from all source and header files.
+ // Find contributions to `compiland` from all source and header files.
std::string path = sc.comp_unit->GetPath();
- auto files = m_session_up->getSourceFilesForCompiland(*cu);
+ auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
+ if (!files)
+ return false;
- // For each source and header file, create a LineSequence for contributions to
- // the cu from that file, and add the sequence.
+ // For each source and header file, create a LineSequence for contributions
+ // to the compiland from that file, and add the sequence.
while (auto file = files->getNext()) {
std::unique_ptr<LineSequence> sequence(
line_table->CreateLineSequenceContainer());
- auto lines = m_session_up->findLineNumbers(*cu, *file);
+ auto lines = m_session_up->findLineNumbers(*compiland_up, *file);
+ if (!lines)
+ continue;
int entry_count = lines->getChildCount();
uint64_t prev_addr;
@@ -646,8 +1563,8 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
uint32_t col = line->getColumnNumber();
uint32_t source_idx = index_map[source_id];
- // There was a gap between the current entry and the previous entry if the
- // addresses don't perfectly line up.
+ // There was a gap between the current entry and the previous entry if
+ // the addresses don't perfectly line up.
bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
// Before inserting the current entry, insert a terminal entry at the end
@@ -657,6 +1574,9 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
line_table->AppendLineEntryToSequence(
sequence.get(), prev_addr + prev_length, prev_line, 0,
prev_source_idx, false, false, false, false, true);
+
+ line_table->InsertSequence(sequence.release());
+ sequence.reset(line_table->CreateLineSequenceContainer());
}
if (ShouldAddLine(match_line, lno, length)) {
@@ -667,10 +1587,12 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
m_session_up->findSymbolByAddress(addr, PDB_SymType::Function);
if (func) {
auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>();
- is_prologue = (addr == prologue->getVirtualAddress());
+ if (prologue)
+ is_prologue = (addr == prologue->getVirtualAddress());
auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>();
- is_epilogue = (addr == epilogue->getVirtualAddress());
+ if (epilogue)
+ is_epilogue = (addr == epilogue->getVirtualAddress());
}
line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col,
@@ -694,23 +1616,134 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
line_table->InsertSequence(sequence.release());
}
- sc.comp_unit->SetLineTable(line_table.release());
- return true;
+ if (line_table->GetSize()) {
+ sc.comp_unit->SetLineTable(line_table.release());
+ return true;
+ }
+ return false;
}
void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
- const PDBSymbolCompiland &cu,
+ const PDBSymbolCompiland &compiland,
llvm::DenseMap<uint32_t, uint32_t> &index_map) const {
- // This is a hack, but we need to convert the source id into an index into the
- // support files array. We don't want to do path comparisons to avoid
+ // This is a hack, but we need to convert the source id into an index into
+ // the support files array. We don't want to do path comparisons to avoid
// basename / full path issues that may or may not even be a problem, so we
// use the globally unique source file identifiers. Ideally we could use the
// global identifiers everywhere, but LineEntry currently assumes indices.
- auto source_files = m_session_up->getSourceFilesForCompiland(cu);
- int index = 0;
+ auto source_files = m_session_up->getSourceFilesForCompiland(compiland);
+ if (!source_files)
+ return;
+
+ // LLDB uses the DWARF-like file numeration (one based)
+ int index = 1;
while (auto file = source_files->getNext()) {
uint32_t source_id = file->getUniqueId();
index_map[source_id] = index++;
}
}
+
+lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress(
+ const lldb_private::Address &so_addr) {
+ lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
+ if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+ return nullptr;
+
+ // If it is a PDB function's vm addr, this is the first sure bet.
+ if (auto lines =
+ m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/1)) {
+ if (auto first_line = lines->getNext())
+ return ParseCompileUnitForUID(first_line->getCompilandId());
+ }
+
+ // Otherwise we resort to section contributions.
+ if (auto sec_contribs = m_session_up->getSectionContribs()) {
+ while (auto section = sec_contribs->getNext()) {
+ auto va = section->getVirtualAddress();
+ if (file_vm_addr >= va && file_vm_addr < va + section->getLength())
+ return ParseCompileUnitForUID(section->getCompilandId());
+ }
+ }
+ return nullptr;
+}
+
+Mangled
+SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) {
+ Mangled mangled;
+ auto func_name = pdb_func.getName();
+ auto func_undecorated_name = pdb_func.getUndecoratedName();
+ std::string func_decorated_name;
+
+ // Seek from public symbols for non-static function's decorated name if any.
+ // For static functions, they don't have undecorated names and aren't exposed
+ // in Public Symbols either.
+ if (!func_undecorated_name.empty()) {
+ auto result_up = m_global_scope_up->findChildren(
+ PDB_SymType::PublicSymbol, func_undecorated_name,
+ PDB_NameSearchFlags::NS_UndecoratedName);
+ if (result_up) {
+ while (auto symbol_up = result_up->getNext()) {
+ // For a public symbol, it is unique.
+ lldbassert(result_up->getChildCount() == 1);
+ if (auto *pdb_public_sym =
+ llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>(
+ symbol_up.get())) {
+ if (pdb_public_sym->isFunction()) {
+ func_decorated_name = pdb_public_sym->getName();
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!func_decorated_name.empty()) {
+ mangled.SetMangledName(ConstString(func_decorated_name));
+
+ // For MSVC, format of C funciton's decorated name depends on calling
+ // conventon. Unfortunately none of the format is recognized by current
+ // LLDB. For example, `_purecall` is a __cdecl C function. From PDB,
+ // `__purecall` is retrieved as both its decorated and undecorated name
+ // (using PDBSymbolFunc::getUndecoratedName method). However `__purecall`
+ // string is not treated as mangled in LLDB (neither `?` nor `_Z` prefix).
+ // Mangled::GetDemangledName method will fail internally and caches an
+ // empty string as its undecorated name. So we will face a contradition
+ // here for the same symbol:
+ // non-empty undecorated name from PDB
+ // empty undecorated name from LLDB
+ if (!func_undecorated_name.empty() &&
+ mangled.GetDemangledName(mangled.GuessLanguage()).IsEmpty())
+ mangled.SetDemangledName(ConstString(func_undecorated_name));
+
+ // LLDB uses several flags to control how a C++ decorated name is
+ // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. So the
+ // yielded name could be different from what we retrieve from
+ // PDB source unless we also apply same flags in getting undecorated
+ // name through PDBSymbolFunc::getUndecoratedNameEx method.
+ if (!func_undecorated_name.empty() &&
+ mangled.GetDemangledName(mangled.GuessLanguage()) !=
+ ConstString(func_undecorated_name))
+ mangled.SetDemangledName(ConstString(func_undecorated_name));
+ } else if (!func_undecorated_name.empty()) {
+ mangled.SetDemangledName(ConstString(func_undecorated_name));
+ } else if (!func_name.empty())
+ mangled.SetValue(ConstString(func_name), false);
+
+ return mangled;
+}
+
+bool SymbolFilePDB::DeclContextMatchesThisSymbolFile(
+ const lldb_private::CompilerDeclContext *decl_ctx) {
+ if (decl_ctx == nullptr || !decl_ctx->IsValid())
+ return true;
+
+ TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem();
+ if (!decl_ctx_type_system)
+ return false;
+ TypeSystem *type_system = GetTypeSystemForLanguage(
+ decl_ctx_type_system->GetMinimumLanguage(nullptr));
+ if (decl_ctx_type_system == type_system)
+ return true; // The type systems match, return true
+
+ return false;
+}
diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index eef96be8d1fe..96b62d68a6c2 100644
--- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -10,12 +10,15 @@
#ifndef lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
#define lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
+#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/VariableList.h"
#include "lldb/Utility/UserID.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
class SymbolFilePDB : public lldb_private::SymbolFile {
public:
@@ -108,11 +111,11 @@ public:
uint32_t
FindGlobalVariables(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t FindGlobalVariables(const lldb_private::RegularExpression &regex,
- bool append, uint32_t max_matches,
+ uint32_t max_matches,
lldb_private::VariableList &variables) override;
uint32_t
@@ -141,8 +144,7 @@ public:
bool append, lldb_private::TypeMap &types) override;
void FindTypesByRegex(const lldb_private::RegularExpression &regex,
- uint32_t max_matches,
- lldb_private::TypeMap &types);
+ uint32_t max_matches, lldb_private::TypeMap &types);
lldb_private::TypeList *GetTypeList() override;
@@ -167,25 +169,76 @@ public:
const llvm::pdb::IPDBSession &GetPDBSession() const;
private:
- lldb::CompUnitSP ParseCompileUnitForSymIndex(uint32_t id);
+ lldb::CompUnitSP ParseCompileUnitForUID(uint32_t id,
+ uint32_t index = UINT32_MAX);
bool ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc,
uint32_t match_line);
void BuildSupportFileIdToSupportFileIndexMap(
- const llvm::pdb::PDBSymbolCompiland &cu,
+ const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
llvm::DenseMap<uint32_t, uint32_t> &index_map) const;
void FindTypesByName(const std::string &name, uint32_t max_matches,
lldb_private::TypeMap &types);
+ std::string GetMangledForPDBData(const llvm::pdb::PDBSymbolData &pdb_data);
+
+ lldb::VariableSP
+ ParseVariableForPDBData(const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbolData &pdb_data);
+
+ size_t ParseVariables(const lldb_private::SymbolContext &sc,
+ const llvm::pdb::PDBSymbol &pdb_data,
+ lldb_private::VariableList *variable_list = nullptr);
+
+ lldb::CompUnitSP
+ GetCompileUnitContainsAddress(const lldb_private::Address &so_addr);
+
+ typedef std::vector<lldb_private::Type *> TypeCollection;
+
+ void GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
+ uint32_t type_mask,
+ TypeCollection &type_collection);
+
+ lldb_private::Function *
+ ParseCompileUnitFunctionForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func,
+ const lldb_private::SymbolContext &sc);
+
+ void GetCompileUnitIndex(const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
+ uint32_t &index);
+
+ std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
+ GetPDBCompilandByUID(uint32_t uid);
+
+ lldb_private::Mangled
+ GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func);
+
+ bool ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
+ bool include_inlines,
+ lldb_private::SymbolContextList &sc_list);
+
+ bool ResolveFunction(uint32_t uid, bool include_inlines,
+ lldb_private::SymbolContextList &sc_list);
+
+ void CacheFunctionNames();
+
+ bool DeclContextMatchesThisSymbolFile(
+ const lldb_private::CompilerDeclContext *decl_ctx);
+
llvm::DenseMap<uint32_t, lldb::CompUnitSP> m_comp_units;
llvm::DenseMap<uint32_t, lldb::TypeSP> m_types;
+ llvm::DenseMap<uint32_t, lldb::VariableSP> m_variables;
std::vector<lldb::TypeSP> m_builtin_types;
std::unique_ptr<llvm::pdb::IPDBSession> m_session_up;
+ std::unique_ptr<llvm::pdb::PDBSymbolExe> m_global_scope_up;
uint32_t m_cached_compile_unit_count;
std::unique_ptr<lldb_private::CompilerDeclContext> m_tu_decl_ctx_up;
+
+ lldb_private::UniqueCStringMap<uint32_t> m_func_full_names;
+ lldb_private::UniqueCStringMap<uint32_t> m_func_base_names;
+ lldb_private::UniqueCStringMap<uint32_t> m_func_method_names;
};
#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index dbc1b9ee5470..64e2daf60ee5 100644
--- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -63,9 +63,9 @@ uint32_t SymbolFileSymtab::CalculateAbilities() {
const Symtab *symtab = m_obj_file->GetSymtab();
if (symtab) {
//----------------------------------------------------------------------
- // The snippet of code below will get the indexes the module symbol
- // table entries that are code, data, or function related (debug info),
- // sort them by value (address) and dump the sorted symbols.
+ // The snippet of code below will get the indexes the module symbol table
+ // entries that are code, data, or function related (debug info), sort
+ // them by value (address) and dump the sorted symbols.
//----------------------------------------------------------------------
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile,
m_source_indexes)) {
@@ -105,24 +105,21 @@ uint32_t SymbolFileSymtab::CalculateAbilities() {
}
uint32_t SymbolFileSymtab::GetNumCompileUnits() {
- // If we don't have any source file symbols we will just have one compile unit
- // for
- // the entire object file
+ // If we don't have any source file symbols we will just have one compile
+ // unit for the entire object file
if (m_source_indexes.empty())
return 0;
// If we have any source file symbols we will logically organize the object
- // symbols
- // using these.
+ // symbols using these.
return m_source_indexes.size();
}
CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) {
CompUnitSP cu_sp;
- // If we don't have any source file symbols we will just have one compile unit
- // for
- // the entire object file
+ // If we don't have any source file symbols we will just have one compile
+ // unit for the entire object file
if (idx < m_source_indexes.size()) {
const Symbol *cu_symbol =
m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
@@ -152,13 +149,12 @@ size_t SymbolFileSymtab::ParseCompileUnitFunctions(const SymbolContext &sc) {
//
// const uint32_t prefix_len = strlen(prefix);
- // If we don't have any source file symbols we will just have one compile unit
- // for
- // the entire object file
+ // If we don't have any source file symbols we will just have one compile
+ // unit for the entire object file
if (m_source_indexes.empty()) {
- // The only time we will have a user ID of zero is when we don't have
- // and source file symbols and we declare one compile unit for the
- // entire object file
+ // The only time we will have a user ID of zero is when we don't have and
+ // source file symbols and we declare one compile unit for the entire
+ // object file
if (!m_func_indexes.empty()) {
}
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index a25119684c28..d24510966878 100644
--- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -57,9 +57,9 @@ const char *SymbolVendorELF::GetPluginDescriptionStatic() {
//----------------------------------------------------------------------
// CreateInstance
//
-// Platforms can register a callback to use when creating symbol
-// vendors to allow for complex debug information file setups, and to
-// also allow for finding separate debug information files.
+// Platforms can register a callback to use when creating symbol vendors to
+// allow for complex debug information file setups, and to also allow for
+// finding separate debug information files.
//----------------------------------------------------------------------
SymbolVendor *
SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
@@ -112,11 +112,9 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(),
dsym_file_data_sp, dsym_file_data_offset);
if (dsym_objfile_sp) {
- // This objfile is for debugging purposes. Sadly, ObjectFileELF won't be
- // able
- // to figure this out consistently as the symbol file may not have
- // stripped the
- // code sections, etc.
+ // This objfile is for debugging purposes. Sadly, ObjectFileELF won't
+ // be able to figure this out consistently as the symbol file may not
+ // have stripped the code sections, etc.
dsym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo);
SymbolVendorELF *symbol_vendor = new SymbolVendorELF(module_sp);
@@ -134,7 +132,7 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets,
- eSectionTypeELFSymbolTable,
+ eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink,
};
for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]);
++idx) {
diff --git a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
index b3fb05e652d9..c69eb7fd51c7 100644
--- a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -94,9 +94,9 @@ const char *SymbolVendorMacOSX::GetPluginDescriptionStatic() {
//----------------------------------------------------------------------
// CreateInstance
//
-// Platforms can register a callback to use when creating symbol
-// vendors to allow for complex debug information file setups, and to
-// also allow for finding separate debug information files.
+// Platforms can register a callback to use when creating symbol vendors to
+// allow for complex debug information file setups, and to also allow for
+// finding separate debug information files.
//----------------------------------------------------------------------
SymbolVendor *
SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
@@ -130,14 +130,14 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
"SymbolVendorMacOSX::CreateInstance (module = %s) locate dSYM",
module_sp->GetFileSpec().GetPath().c_str());
- // First check to see if the module has a symbol file in mind already.
- // If it does, then we MUST use that.
+ // First check to see if the module has a symbol file in mind already. If
+ // it does, then we MUST use that.
FileSpec dsym_fspec(module_sp->GetSymbolFileFileSpec());
ObjectFileSP dsym_objfile_sp;
if (!dsym_fspec) {
- // No symbol file was specified in the module, lets try and find
- // one ourselves.
+ // No symbol file was specified in the module, lets try and find one
+ // ourselves.
FileSpec file_spec = obj_file->GetFileSpec();
if (!file_spec)
file_spec = module_sp->GetFileSpec();
@@ -179,24 +179,8 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
std::string DBGBuildSourcePath;
std::string DBGSourcePath;
- plist.GetValueAsString("DBGBuildSourcePath",
- DBGBuildSourcePath);
- plist.GetValueAsString("DBGSourcePath", DBGSourcePath);
- if (!DBGBuildSourcePath.empty() &&
- !DBGSourcePath.empty()) {
- if (DBGSourcePath[0] == '~') {
- FileSpec resolved_source_path(DBGSourcePath.c_str(),
- true);
- DBGSourcePath = resolved_source_path.GetPath();
- }
- module_sp->GetSourceMappingList().Append(
- ConstString(DBGBuildSourcePath),
- ConstString(DBGSourcePath), true);
- }
-
// DBGSourcePathRemapping is a dictionary in the plist
- // with
- // keys which are DBGBuildSourcePath file paths and
+ // with keys which are DBGBuildSourcePath file paths and
// values which are DBGSourcePath file paths
StructuredData::ObjectSP plist_sp =
@@ -208,17 +192,14 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
->GetValueForKey("DBGSourcePathRemapping")
->GetAsDictionary()) {
- // In an early version of DBGSourcePathRemapping, the
- // DBGSourcePath
- // values were incorrect. If we have a newer style
- // DBGSourcePathRemapping, there will be a DBGVersion
- // key in the plist with version 2 or higher.
+ // If DBGVersion 1 or DBGVersion missing, ignore DBGSourcePathRemapping.
+ // If DBGVersion 2, strip last two components of path remappings from
+ // entries to fix an issue with a specific set of
+ // DBGSourcePathRemapping entries that lldb worked
+ // with.
+ // If DBGVersion 3, trust & use the source path remappings as-is.
//
- // If this is an old style DBGSourcePathRemapping,
- // ignore the
- // value half of the key-value remappings and use reuse
- // the original
- // gloal DBGSourcePath string.
+
bool new_style_source_remapping_dictionary = false;
bool do_truncate_remapping_names = false;
std::string original_DBGSourcePath_value =
@@ -268,10 +249,12 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
}
module_sp->GetSourceMappingList().Append(
key, ConstString(DBGSourcePath), true);
- // With version 2 of DBGSourcePathRemapping, we can chop off the
- // last two filename parts from the source remapping and get a
- // more general source remapping that still works. Add this as
- // another option in addition to the full source path remap.
+ // With version 2 of DBGSourcePathRemapping, we
+ // can chop off the last two filename parts
+ // from the source remapping and get a more
+ // general source remapping that still works.
+ // Add this as another option in addition to
+ // the full source path remap.
if (do_truncate_remapping_names) {
FileSpec build_path(key.AsCString(), false);
FileSpec source_path(DBGSourcePath.c_str(), false);
@@ -287,6 +270,24 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
return true;
});
}
+
+ // If we have a DBGBuildSourcePath + DBGSourcePath pair,
+ // append those to the source path remappings.
+
+ plist.GetValueAsString("DBGBuildSourcePath",
+ DBGBuildSourcePath);
+ plist.GetValueAsString("DBGSourcePath", DBGSourcePath);
+ if (!DBGBuildSourcePath.empty() &&
+ !DBGSourcePath.empty()) {
+ if (DBGSourcePath[0] == '~') {
+ FileSpec resolved_source_path(DBGSourcePath.c_str(),
+ true);
+ DBGSourcePath = resolved_source_path.GetPath();
+ }
+ module_sp->GetSourceMappingList().Append(
+ ConstString(DBGBuildSourcePath),
+ ConstString(DBGSourcePath), true);
+ }
}
}
}
@@ -300,9 +301,9 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
}
}
- // Just create our symbol vendor using the current objfile as this is either
- // an executable with no dSYM (that we could locate), an executable with
- // a dSYM that has a UUID that doesn't match.
+ // Just create our symbol vendor using the current objfile as this is
+ // either an executable with no dSYM (that we could locate), an executable
+ // with a dSYM that has a UUID that doesn't match.
symbol_vendor->AddSymbolFileRepresentation(obj_file->shared_from_this());
}
return symbol_vendor;
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
index 3f0c7db676f3..007a59378fc5 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
@@ -119,20 +119,18 @@ void AppleGetItemInfoHandler::Detach() {
}
// Compile our __lldb_backtrace_recording_get_item_info() function (from the
-// source above in g_get_item_info_function_code) if we don't find that function
-// in the inferior
-// already with USE_BUILTIN_FUNCTION defined. (e.g. this would be the case for
-// testing.)
+// source above in g_get_item_info_function_code) if we don't find that
+// function in the inferior already with USE_BUILTIN_FUNCTION defined. (e.g.
+// this would be the case for testing.)
//
-// Insert the __lldb_backtrace_recording_get_item_info into the inferior process
-// if needed.
+// Insert the __lldb_backtrace_recording_get_item_info into the inferior
+// process if needed.
//
// Write the get_item_info_arglist into the inferior's memory space to prepare
// for the call.
//
// Returns the address of the arguments written down in the inferior process,
-// which can be used to
-// make the function call.
+// which can be used to make the function call.
lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction(
Thread &thread, ValueList &get_item_info_arglist) {
@@ -146,7 +144,8 @@ lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction(
{
std::lock_guard<std::mutex> guard(m_get_item_info_function_mutex);
- // First stage is to make the UtilityFunction to hold our injected function:
+ // First stage is to make the UtilityFunction to hold our injected
+ // function:
if (!m_get_item_info_impl_code.get()) {
if (g_get_item_info_function_code != NULL) {
@@ -209,10 +208,9 @@ lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction(
diagnostics.Clear();
// Now write down the argument values for this particular call. This looks
- // like it might be a race condition
- // if other threads were calling into here, but actually it isn't because we
- // allocate a new args structure for
- // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+ // like it might be a race condition if other threads were calling into here,
+ // but actually it isn't because we allocate a new args structure for this
+ // call by passing args_addr = LLDB_INVALID_ADDRESS...
if (!get_item_info_caller->WriteFunctionArguments(
exe_ctx, args_addr, get_item_info_arglist, diagnostics)) {
@@ -272,8 +270,7 @@ AppleGetItemInfoHandler::GetItemInfo(Thread &thread, uint64_t item,
// uint64_t page_to_free_size)
// Where the return_buffer argument points to a 24 byte region of memory
- // already allocated by lldb in
- // the inferior process.
+ // already allocated by lldb in the inferior process.
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
index e3d03a6f9484..0de32bf11416 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
@@ -121,11 +121,10 @@ void AppleGetPendingItemsHandler::Detach() {
}
}
-// Compile our __lldb_backtrace_recording_get_pending_items() function (from the
-// source above in g_get_pending_items_function_code) if we don't find that
-// function in the inferior
-// already with USE_BUILTIN_FUNCTION defined. (e.g. this would be the case for
-// testing.)
+// Compile our __lldb_backtrace_recording_get_pending_items() function (from
+// the source above in g_get_pending_items_function_code) if we don't find that
+// function in the inferior already with USE_BUILTIN_FUNCTION defined. (e.g.
+// this would be the case for testing.)
//
// Insert the __lldb_backtrace_recording_get_pending_items into the inferior
// process if needed.
@@ -134,8 +133,7 @@ void AppleGetPendingItemsHandler::Detach() {
// prepare for the call.
//
// Returns the address of the arguments written down in the inferior process,
-// which can be used to
-// make the function call.
+// which can be used to make the function call.
lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction(
Thread &thread, ValueList &get_pending_items_arglist) {
@@ -212,10 +210,9 @@ lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction(
}
// Now write down the argument values for this particular call. This looks
- // like it might be a race condition
- // if other threads were calling into here, but actually it isn't because we
- // allocate a new args structure for
- // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+ // like it might be a race condition if other threads were calling into here,
+ // but actually it isn't because we allocate a new args structure for this
+ // call by passing args_addr = LLDB_INVALID_ADDRESS...
if (!get_pending_items_caller->WriteFunctionArguments(
exe_ctx, args_addr, get_pending_items_arglist, diagnostics)) {
@@ -279,8 +276,7 @@ AppleGetPendingItemsHandler::GetPendingItems(Thread &thread, addr_t queue,
// uint64_t page_to_free_size)
// Where the return_buffer argument points to a 24 byte region of memory
- // already allocated by lldb in
- // the inferior process.
+ // already allocated by lldb in the inferior process.
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
index c1654eb62ccc..7855b3603a3a 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
@@ -118,9 +118,9 @@ void AppleGetQueuesHandler::Detach() {
}
// Construct a CompilerType for the structure that
-// g_get_current_queues_function_code will return by value
-// so we can extract the fields after performing the function call.
-// i.e. we are getting this struct returned to us:
+// g_get_current_queues_function_code will return by value so we can extract
+// the fields after performing the function call. i.e. we are getting this
+// struct returned to us:
//
// struct get_current_queues_return_values
// {
@@ -130,11 +130,9 @@ void AppleGetQueuesHandler::Detach() {
// };
// Compile our __lldb_backtrace_recording_get_current_queues() function (from
-// the
-// source above in g_get_current_queues_function_code) if we don't find that
-// function in the inferior
-// already with USE_BUILTIN_FUNCTION defined. (e.g. this would be the case for
-// testing.)
+// the source above in g_get_current_queues_function_code) if we don't find
+// that function in the inferior already with USE_BUILTIN_FUNCTION defined.
+// (e.g. this would be the case for testing.)
//
// Insert the __lldb_backtrace_recording_get_current_queues into the inferior
// process if needed.
@@ -143,8 +141,7 @@ void AppleGetQueuesHandler::Detach() {
// the call.
//
// Returns the address of the arguments written down in the inferior process,
-// which can be used to
-// make the function call.
+// which can be used to make the function call.
lldb::addr_t
AppleGetQueuesHandler::SetupGetQueuesFunction(Thread &thread,
@@ -217,10 +214,9 @@ AppleGetQueuesHandler::SetupGetQueuesFunction(Thread &thread,
diagnostics.Clear();
// Now write down the argument values for this particular call. This looks
- // like it might be a race condition
- // if other threads were calling into here, but actually it isn't because we
- // allocate a new args structure for
- // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+ // like it might be a race condition if other threads were calling into here,
+ // but actually it isn't because we allocate a new args structure for this
+ // call by passing args_addr = LLDB_INVALID_ADDRESS...
if (!get_queues_caller->WriteFunctionArguments(
exe_ctx, args_addr, get_queues_arglist, diagnostics)) {
@@ -280,8 +276,7 @@ AppleGetQueuesHandler::GetCurrentQueues(Thread &thread, addr_t page_to_free,
// uint64_t page_to_free_size);
// Where the return_buffer argument points to a 24 byte region of memory
- // already allocated by lldb in
- // the inferior process.
+ // already allocated by lldb in the inferior process.
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
index 8d83922af1e7..09ab6600a9f0 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
@@ -128,11 +128,9 @@ void AppleGetThreadItemInfoHandler::Detach() {
}
// Compile our __lldb_backtrace_recording_get_thread_item_info() function (from
-// the
-// source above in g_get_thread_item_info_function_code) if we don't find that
-// function in the inferior
-// already with USE_BUILTIN_FUNCTION defined. (e.g. this would be the case for
-// testing.)
+// the source above in g_get_thread_item_info_function_code) if we don't find
+// that function in the inferior already with USE_BUILTIN_FUNCTION defined.
+// (e.g. this would be the case for testing.)
//
// Insert the __lldb_backtrace_recording_get_thread_item_info into the inferior
// process if needed.
@@ -141,8 +139,7 @@ void AppleGetThreadItemInfoHandler::Detach() {
// prepare for the call.
//
// Returns the address of the arguments written down in the inferior process,
-// which can be used to
-// make the function call.
+// which can be used to make the function call.
lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction(
Thread &thread, ValueList &get_thread_item_info_arglist) {
@@ -221,10 +218,9 @@ lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction(
diagnostics.Clear();
// Now write down the argument values for this particular call. This looks
- // like it might be a race condition
- // if other threads were calling into here, but actually it isn't because we
- // allocate a new args structure for
- // this call by passing args_addr = LLDB_INVALID_ADDRESS...
+ // like it might be a race condition if other threads were calling into here,
+ // but actually it isn't because we allocate a new args structure for this
+ // call by passing args_addr = LLDB_INVALID_ADDRESS...
if (!get_thread_item_info_caller->WriteFunctionArguments(
exe_ctx, args_addr, get_thread_item_info_arglist, diagnostics)) {
@@ -266,8 +262,7 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread,
// Set up the arguments for a call to
- // struct get_thread_item_info_return_values
- // {
+ // struct get_thread_item_info_return_values {
// uint64_t item_info_buffer_ptr; /* the address of the items buffer
// from libBacktraceRecording */
// uint64_t item_info_buffer_size; /* the size of the items buffer from
@@ -283,8 +278,7 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread,
// uint64_t page_to_free_size)
// Where the return_buffer argument points to a 24 byte region of memory
- // already allocated by lldb in
- // the inferior process.
+ // already allocated by lldb in the inferior process.
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
index 1a538b236c15..4748d5e8622e 100644
--- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
@@ -34,9 +34,9 @@ using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
-// Create an instance of this class. This function is filled into
-// the plugin info class that gets handed out by the plugin factory and
-// allows the lldb to instantiate an instance of this class.
+// Create an instance of this class. This function is filled into the plugin
+// info class that gets handed out by the plugin factory and allows the lldb to
+// instantiate an instance of this class.
//----------------------------------------------------------------------
SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) {
bool create = false;
@@ -125,17 +125,15 @@ SystemRuntimeMacOSX::GetQueueNameFromThreadQAddress(addr_t dispatch_qaddr) {
ReadLibdispatchOffsets();
if (m_libdispatch_offsets.IsValid()) {
// dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
- // thread -
- // deref it to get the address of the dispatch_queue_t structure for this
- // thread's
- // queue.
+ // thread - deref it to get the address of the dispatch_queue_t structure
+ // for this thread's queue.
Status error;
addr_t dispatch_queue_addr =
m_process->ReadPointerFromMemory(dispatch_qaddr, error);
if (error.Success()) {
if (m_libdispatch_offsets.dqo_version >= 4) {
- // libdispatch versions 4+, pointer to dispatch name is in the
- // queue structure.
+ // libdispatch versions 4+, pointer to dispatch name is in the queue
+ // structure.
addr_t pointer_to_label_address =
dispatch_queue_addr + m_libdispatch_offsets.dqo_label;
addr_t label_addr =
@@ -248,10 +246,8 @@ SystemRuntimeMacOSX::GetQueueIDFromThreadQAddress(lldb::addr_t dispatch_qaddr) {
ReadLibdispatchOffsets();
if (m_libdispatch_offsets.IsValid()) {
// dispatch_qaddr is from a thread_info(THREAD_IDENTIFIER_INFO) call for a
- // thread -
- // deref it to get the address of the dispatch_queue_t structure for this
- // thread's
- // queue.
+ // thread - deref it to get the address of the dispatch_queue_t structure
+ // for this thread's queue.
Status error;
uint64_t dispatch_queue_addr =
m_process->ReadPointerFromMemory(dispatch_qaddr, error);
@@ -287,8 +283,8 @@ void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() {
dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType(
g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
- // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion") and
- // later
+ // libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion")
+ // and later
if (dispatch_queue_offsets_symbol == NULL) {
ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib", false));
module_sp = m_process->GetTarget().GetImages().FindFirstModule(
@@ -320,8 +316,7 @@ void SystemRuntimeMacOSX::ReadLibdispatchOffsets() {
lldb::offset_t data_offset = 0;
// The struct LibdispatchOffsets is a series of uint16_t's - extract them
- // all
- // in one big go.
+ // all in one big go.
data.GetU16(&data_offset, &m_libdispatch_offsets.dqo_version,
sizeof(struct LibdispatchOffsets) / sizeof(uint16_t));
}
@@ -368,8 +363,7 @@ void SystemRuntimeMacOSX::ReadLibpthreadOffsets() {
lldb::offset_t data_offset = 0;
// The struct LibpthreadOffsets is a series of uint16_t's - extract them
- // all
- // in one big go.
+ // all in one big go.
data.GetU16(&data_offset, &m_libpthread_offsets.plo_version,
sizeof(struct LibpthreadOffsets) / sizeof(uint16_t));
}
@@ -407,10 +401,8 @@ void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() {
if (m_dispatch_tsd_indexes_addr != LLDB_INVALID_ADDRESS) {
// We don't need to check the version number right now, it will be at least 2,
-// but
-// keep this code around to fetch just the version # for the future where we
-// need
-// to fetch alternate versions of the struct.
+// but keep this code around to fetch just the version # for the future where
+// we need to fetch alternate versions of the struct.
#if 0
uint16_t dti_version = 2;
Address dti_struct_addr;
@@ -473,12 +465,9 @@ ThreadSP SystemRuntimeMacOSX::GetExtendedBacktraceThread(ThreadSP real_thread,
Status error;
// real_thread is either an actual, live thread (in which case we need to
- // call into
- // libBacktraceRecording to find its originator) or it is an extended
- // backtrace itself,
- // in which case we get the token from it and call into
- // libBacktraceRecording to find
- // the originator of that token.
+ // call into libBacktraceRecording to find its originator) or it is an
+ // extended backtrace itself, in which case we get the token from it and
+ // call into libBacktraceRecording to find the originator of that token.
if (real_thread->GetExtendedBacktraceToken() != LLDB_INVALID_ADDRESS) {
originating_thread_sp = GetExtendedBacktraceFromItemRef(
@@ -735,13 +724,11 @@ void SystemRuntimeMacOSX::PopulateQueueList(
}
// We either didn't have libBacktraceRecording (and need to create the queues
- // list based on threads)
- // or we did get the queues list from libBacktraceRecording but some special
- // queues may not be
- // included in its information. This is needed because libBacktraceRecording
- // will only list queues with pending or running items by default - but the
- // magic com.apple.main-thread
- // queue on thread 1 is always around.
+ // list based on threads) or we did get the queues list from
+ // libBacktraceRecording but some special queues may not be included in its
+ // information. This is needed because libBacktraceRecording will only list
+ // queues with pending or running items by default - but the magic com.apple
+ // .main-thread queue on thread 1 is always around.
for (ThreadSP thread_sp : m_process->Threads()) {
if (thread_sp->GetAssociatedWithLibdispatchQueue() != eLazyBoolNo) {
@@ -769,12 +756,10 @@ void SystemRuntimeMacOSX::PopulateQueueList(
}
// Returns either an array of introspection_dispatch_item_info_ref's for the
-// pending items on
-// a queue or an array introspection_dispatch_item_info_ref's and code addresses
-// for the
-// pending items on a queue. The information about each of these pending items
-// then needs to
-// be fetched individually by passing the ref to libBacktraceRecording.
+// pending items on a queue or an array introspection_dispatch_item_info_ref's
+// and code addresses for the pending items on a queue. The information about
+// each of these pending items then needs to be fetched individually by passing
+// the ref to libBacktraceRecording.
SystemRuntimeMacOSX::PendingItemsForQueue
SystemRuntimeMacOSX::GetPendingItemRefsForQueue(lldb::addr_t queue) {
@@ -927,8 +912,8 @@ void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR(
offset_t offset = 0;
uint64_t queues_read = 0;
- // The information about the queues is stored in this format (v1):
- // typedef struct introspection_dispatch_queue_info_s {
+ // The information about the queues is stored in this format (v1): typedef
+ // struct introspection_dispatch_queue_info_s {
// uint32_t offset_to_next;
// dispatch_queue_t queue;
// uint64_t serialnum; // queue's serialnum in the process, as
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index f8aca4d1283b..54e182b30b6f 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -12,6 +12,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/DumpDataExtractor.h"
+#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/ExecutionContext.h"
@@ -58,8 +59,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid() &&
m_inst_emulator_ap.get()) {
- // The instruction emulation subclass setup the unwind plan for the
- // first instruction.
+ // The instruction emulation subclass setup the unwind plan for the first
+ // instruction.
m_inst_emulator_ap->CreateFunctionEntryUnwind(unwind_plan);
// CreateFunctionEntryUnwind should have created the first row. If it
@@ -90,9 +91,9 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
m_register_values.clear();
m_pushed_regs.clear();
- // Initialize the CFA with a known value. In the 32 bit case
- // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
- // We use the address byte size to be safe for any future address sizes
+ // Initialize the CFA with a known value. In the 32 bit case it will be
+ // 0x80000000, and in the 64 bit case 0x8000000000000000. We use the
+ // address byte size to be safe for any future address sizes
m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
RegisterValue cfa_reg_value;
cfa_reg_value.SetUInt(m_initial_sp, m_cfa_reg_info.byte_size);
@@ -105,14 +106,12 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
Instruction *inst = inst_list.GetInstructionAtIndex(0).get();
const lldb::addr_t base_addr = inst->GetAddress().GetFileAddress();
- // Map for storing the unwind plan row and the value of the registers at
- // a given offset.
- // When we see a forward branch we add a new entry to this map with the
- // actual unwind plan
- // row and register context for the target address of the branch as the
- // current data have
- // to be valid for the target address of the branch too if we are in the
- // same function.
+ // Map for storing the unwind plan row and the value of the registers
+ // at a given offset. When we see a forward branch we add a new entry
+ // to this map with the actual unwind plan row and register context for
+ // the target address of the branch as the current data have to be
+ // valid for the target address of the branch too if we are in the same
+ // function.
std::map<lldb::addr_t, std::pair<UnwindPlan::RowSP, RegisterValueMap>>
saved_unwind_states;
@@ -128,15 +127,14 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
saved_unwind_states.insert({0, {last_row, m_register_values}});
// cache the pc register number (in whatever register numbering this
- // UnwindPlan uses) for
- // quick reference during instruction parsing.
+ // UnwindPlan uses) for quick reference during instruction parsing.
RegisterInfo pc_reg_info;
m_inst_emulator_ap->GetRegisterInfo(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info);
// cache the return address register number (in whatever register
- // numbering this UnwindPlan uses) for
- // quick reference during instruction parsing.
+ // numbering this UnwindPlan uses) for quick reference during
+ // instruction parsing.
RegisterInfo ra_reg_info;
m_inst_emulator_ap->GetRegisterInfo(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info);
@@ -160,12 +158,11 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
"Unwind row for the function entry missing");
--it; // Move it to the row corresponding to the current offset
- // If the offset of m_curr_row don't match with the offset we see in
- // saved_unwind_states
- // then we have to update m_curr_row and m_register_values based on
- // the saved values. It
- // is happenning after we processed an epilogue and a return to
- // caller instruction.
+ // If the offset of m_curr_row don't match with the offset we see
+ // in saved_unwind_states then we have to update m_curr_row and
+ // m_register_values based on the saved values. It is happening
+ // after we processed an epilogue and a return to caller
+ // instruction.
if (it->second.first->GetOffset() != m_curr_row->GetOffset()) {
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *it->second.first;
@@ -181,10 +178,9 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
if (m_inst_emulator_ap->GetInstructionCondition() !=
EmulateInstruction::UnconditionalCondition &&
saved_unwind_states.count(current_offset) == 0) {
- // If we don't have a saved row for the current offset then save
- // our
- // current state because we will have to restore it after the
- // conditional block.
+ // If we don't have a saved row for the current offset then
+ // save our current state because we will have to restore it
+ // after the conditional block.
auto new_row =
std::make_shared<UnwindPlan::Row>(*m_curr_row.get());
saved_unwind_states.insert(
@@ -192,8 +188,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
}
// If the last instruction was conditional with a different
- // condition
- // then the then current condition then restore the condition.
+ // condition then the then current condition then restore the
+ // condition.
if (last_condition !=
EmulateInstruction::UnconditionalCondition) {
const auto &saved_state =
@@ -211,7 +207,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
replace_existing);
}
- // We are starting a new conditional block at the catual offset
+ // We are starting a new conditional block at the actual offset
condition_block_start_offset = current_offset;
}
@@ -230,8 +226,7 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
eEmulateInstructionOptionIgnoreConditions);
// If the current instruction is a branch forward then save the
- // current CFI information
- // for the offset where we are branching.
+ // current CFI information for the offset where we are branching.
if (m_forward_branch_offset != 0 &&
range.ContainsFileAddress(inst->GetAddress().GetFileAddress() +
m_forward_branch_offset)) {
@@ -247,8 +242,8 @@ bool UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly(
// Were there any changes to the CFI while evaluating this
// instruction?
if (m_curr_row_modified) {
- // Save the modified row if we don't already have a CFI row in the
- // currennt address
+ // Save the modified row if we don't already have a CFI row in
+ // the current address
if (saved_unwind_states.count(
current_offset + inst->GetOpcode().GetByteSize()) == 0) {
m_curr_row->SetOffset(current_offset +
@@ -492,7 +487,7 @@ bool UnwindAssemblyInstEmulation::ReadRegister(EmulateInstruction *instruction,
strm.Printf("UnwindAssemblyInstEmulation::ReadRegister (name = \"%s\") => "
"synthetic_value = %i, value = ",
reg_info->name, synthetic);
- reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+ DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
log->PutString(strm.GetString());
}
return true;
@@ -518,7 +513,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
strm.Printf(
"UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ",
reg_info->name);
- reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+ DumpRegisterValue(reg_value, &strm, reg_info, false, false, eFormatDefault);
strm.PutCString(", context = ");
context.Dump(strm, instruction);
log->PutString(strm.GetString());
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index b8dcd99a53e7..327d0b0e4f71 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -86,12 +86,10 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
LLDB_REGNUM_GENERIC_PC);
// Does this UnwindPlan describe the prologue? I want to see that the CFA is
- // set
- // in terms of the stack pointer plus an offset, and I want to see that rip is
- // retrieved at the CFA-wordsize.
- // If there is no description of the prologue, don't try to augment this
- // eh_frame
- // unwinder code, fall back to assembly parsing instead.
+ // set in terms of the stack pointer plus an offset, and I want to see that
+ // rip is retrieved at the CFA-wordsize. If there is no description of the
+ // prologue, don't try to augment this eh_frame unwinder code, fall back to
+ // assembly parsing instead.
if (first_row->GetCFAValue().GetValueType() !=
UnwindPlan::Row::CFAValue::isRegisterPlusOffset ||
@@ -110,14 +108,13 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
return false;
}
- // It looks like the prologue is described.
- // Is the epilogue described? If it is, no need to do any augmentation.
+ // It looks like the prologue is described. Is the epilogue described? If it
+ // is, no need to do any augmentation.
if (first_row != last_row &&
first_row->GetOffset() != last_row->GetOffset()) {
- // The first & last row have the same CFA register
- // and the same CFA offset value
- // and the CFA register is esp/rsp (the stack pointer).
+ // The first & last row have the same CFA register and the same CFA offset
+ // value and the CFA register is esp/rsp (the stack pointer).
// We're checking that both of them have an unwind rule like "CFA=esp+4" or
// CFA+rsp+8".
@@ -128,8 +125,8 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
last_row->GetCFAValue().GetRegisterNumber() &&
first_row->GetCFAValue().GetOffset() ==
last_row->GetCFAValue().GetOffset()) {
- // Get the register locations for eip/rip from the first & last rows.
- // Are they both CFA plus an offset? Is it the same offset?
+ // Get the register locations for eip/rip from the first & last rows. Are
+ // they both CFA plus an offset? Is it the same offset?
UnwindPlan::Row::RegisterLocation last_row_pc_loc;
if (last_row->GetRegisterInfo(
@@ -139,12 +136,10 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
first_row_pc_loc.GetOffset() == last_row_pc_loc.GetOffset()) {
// One last sanity check: Is the unwind rule for getting the caller
- // pc value
- // "deref the CFA-4" or "deref the CFA-8"?
+ // pc value "deref the CFA-4" or "deref the CFA-8"?
// If so, we have an UnwindPlan that already describes the epilogue
- // and we don't need
- // to modify it at all.
+ // and we don't need to modify it at all.
if (first_row_pc_loc.GetOffset() == -wordsize) {
do_augment_unwindplan = false;
diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index aa15063ac0dc..10a56980594f 100644
--- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -246,8 +246,7 @@ void x86AssemblyInspectionEngine::Initialize(
}
// This function expects an x86 native register number (i.e. the bits stripped
-// out of the
-// actual instruction), not an lldb register number.
+// out of the actual instruction), not an lldb register number.
//
// FIXME: This is ABI dependent, it shouldn't be hardcoded here.
@@ -321,15 +320,14 @@ bool x86AssemblyInspectionEngine::push_imm_pattern_p() {
// pushl imm8(%esp)
//
-// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)'
-// (same byte pattern for 'pushq 0x20(%rsp)' in an x86_64 program)
+// e.g. 0xff 0x74 0x24 0x20 - 'pushl 0x20(%esp)' (same byte pattern for 'pushq
+// 0x20(%rsp)' in an x86_64 program)
//
-// 0xff (with opcode bits '6' in next byte, PUSH r/m32)
-// 0x74 (ModR/M byte with three bits used to specify the opcode)
+// 0xff (with opcode bits '6' in next byte, PUSH r/m32) 0x74 (ModR/M byte with
+// three bits used to specify the opcode)
// mod == b01, opcode == b110, R/M == b100
// "+disp8"
-// 0x24 (SIB byte - scaled index = 0, r32 == esp)
-// 0x20 imm8 value
+// 0x24 (SIB byte - scaled index = 0, r32 == esp) 0x20 imm8 value
bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
if (*m_cur_insn == 0xff) {
@@ -337,9 +335,8 @@ bool x86AssemblyInspectionEngine::push_extended_pattern_p() {
uint8_t opcode = (*(m_cur_insn + 1) >> 3) & 7;
if (opcode == 6) {
// I'm only looking for 0xff /6 here - I
- // don't really care what value is being pushed,
- // just that we're pushing a 32/64 bit value on
- // to the stack is enough.
+ // don't really care what value is being pushed, just that we're pushing
+ // a 32/64 bit value on to the stack is enough.
return true;
}
}
@@ -377,8 +374,8 @@ bool x86AssemblyInspectionEngine::push_reg_p(int &regno) {
return false;
}
-// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
-// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
+// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5] movl %esp, %ebp [0x8b
+// 0xec] or [0x89 0xe5]
bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
uint8_t *p = m_cur_insn;
if (m_wordsize == 8 && *p == 0x48)
@@ -529,16 +526,16 @@ bool x86AssemblyInspectionEngine::call_next_insn_pattern_p() {
(*(p + 3) == 0x0) && (*(p + 4) == 0x0);
}
-// Look for an instruction sequence storing a nonvolatile register
-// on to the stack frame.
+// Look for an instruction sequence storing a nonvolatile register on to the
+// stack frame.
// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4]
-// The offset value returned in rbp_offset will be positive --
-// but it must be subtraced from the frame base register to get
-// the actual location. The positive value returned for the offset
-// is a convention used elsewhere for CFA offsets et al.
+// The offset value returned in rbp_offset will be positive -- but it must be
+// subtraced from the frame base register to get the actual location. The
+// positive value returned for the offset is a convention used elsewhere for
+// CFA offsets et al.
bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
int &regno, int &rbp_offset) {
@@ -550,8 +547,8 @@ bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
src_reg_prefix_bit = REX_W_SRCREG(*p) << 3;
target_reg_prefix_bit = REX_W_DSTREG(*p) << 3;
if (target_reg_prefix_bit == 1) {
- // rbp/ebp don't need a prefix bit - we know this isn't the
- // reg we care about.
+ // rbp/ebp don't need a prefix bit - we know this isn't the reg we care
+ // about.
return false;
}
p++;
@@ -671,18 +668,16 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
*newrow = *row.get();
row.reset(newrow);
- // Track which registers have been saved so far in the prologue.
- // If we see another push of that register, it's not part of the prologue.
- // The register numbers used here are the machine register #'s
- // (i386_register_numbers, x86_64_register_numbers).
+ // Track which registers have been saved so far in the prologue. If we see
+ // another push of that register, it's not part of the prologue. The register
+ // numbers used here are the machine register #'s (i386_register_numbers,
+ // x86_64_register_numbers).
std::vector<bool> saved_registers(32, false);
// Once the prologue has completed we'll save a copy of the unwind
- // instructions
- // If there is an epilogue in the middle of the function, after that epilogue
- // we'll reinstate
- // the unwind setup -- we assume that some code path jumps over the
- // mid-function epilogue
+ // instructions If there is an epilogue in the middle of the function, after
+ // that epilogue we'll reinstate the unwind setup -- we assume that some code
+ // path jumps over the mid-function epilogue
UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
@@ -723,9 +718,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
// This is the start() function (or a pthread equivalent), it starts with a
- // pushl $0x0 which puts the
- // saved pc value of 0 on the stack. In this case we want to pretend we
- // didn't see a stack movement at all --
+ // pushl $0x0 which puts the saved pc value of 0 on the stack. In this
+ // case we want to pretend we didn't see a stack movement at all --
// normally the saved pc value is already on the stack by the time the
// function starts executing.
else if (push_0_pattern_p()) {
@@ -733,9 +727,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
else if (push_reg_p(machine_regno)) {
current_sp_bytes_offset_from_cfa += m_wordsize;
- // the PUSH instruction has moved the stack pointer - if the CFA is set in
- // terms of the stack pointer,
- // we need to add a new row of instructions.
+ // the PUSH instruction has moved the stack pointer - if the CFA is set
+ // in terms of the stack pointer, we need to add a new row of
+ // instructions.
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
row_updated = true;
@@ -772,8 +766,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
// the POP instruction has moved the stack pointer - if the CFA is set in
- // terms of the stack pointer,
- // we need to add a new row of instructions.
+ // terms of the stack pointer, we need to add a new row of instructions.
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
row->GetCFAValue().SetIsRegisterPlusOffset(
m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
@@ -790,13 +783,13 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
}
- // The LEAVE instruction moves the value from rbp into rsp and pops
- // a value off the stack into rbp (restoring the caller's rbp value).
- // It is the opposite of ENTER, or 'push rbp, mov rsp rbp'.
+ // The LEAVE instruction moves the value from rbp into rsp and pops a value
+ // off the stack into rbp (restoring the caller's rbp value). It is the
+ // opposite of ENTER, or 'push rbp, mov rsp rbp'.
else if (leave_pattern_p()) {
// We're going to copy the value in rbp into rsp, so re-set the sp offset
- // based on the CFAValue. Also, adjust it to recognize that we're popping
- // the saved rbp value off the stack.
+ // based on the CFAValue. Also, adjust it to recognize that we're
+ // popping the saved rbp value off the stack.
current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
current_sp_bytes_offset_from_cfa -= m_wordsize;
row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
@@ -822,12 +815,11 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
UnwindPlan::Row::RegisterLocation regloc;
- // stack_offset for 'movq %r15, -80(%rbp)' will be 80.
- // In the Row, we want to express this as the offset from the CFA. If the
- // frame base
- // is rbp (like the above instruction), the CFA offset for rbp is probably
- // 16. So we
- // want to say that the value is stored at the CFA address - 96.
+ // stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
+ // want to express this as the offset from the CFA. If the frame base is
+ // rbp (like the above instruction), the CFA offset for rbp is probably
+ // 16. So we want to say that the value is stored at the CFA address -
+ // 96.
regloc.SetAtCFAPlusOffset(
-(stack_offset + row->GetCFAValue().GetOffset()));
@@ -879,8 +871,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (ret_pattern_p() && prologue_completed_row.get()) {
- // Reinstate the saved prologue setup for any instructions
- // that come after the ret instruction
+ // Reinstate the saved prologue setup for any instructions that come
+ // after the ret instruction
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *prologue_completed_row.get();
@@ -960,16 +952,15 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
if (!addr_start.IsValid())
return false;
- // We either need a live RegisterContext, or we need the UnwindPlan to already
- // be in the lldb register numbering scheme.
+ // We either need a live RegisterContext, or we need the UnwindPlan to
+ // already be in the lldb register numbering scheme.
if (reg_ctx.get() == nullptr &&
unwind_plan.GetRegisterKind() != eRegisterKindLLDB)
return false;
// Is original unwind_plan valid?
- // unwind_plan should have at least one row which is ABI-default (CFA register
- // is sp),
- // and another row in mid-function.
+ // unwind_plan should have at least one row which is ABI-default (CFA
+ // register is sp), and another row in mid-function.
if (unwind_plan.GetRowCount() < 2)
return false;
@@ -994,11 +985,9 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
UnwindPlan::RowSP row(new UnwindPlan::Row(*first_row));
m_cur_insn = data + offset;
- // After a mid-function epilogue we will need to re-insert the original unwind
- // rules
- // so unwinds work for the remainder of the function. These aren't common
- // with clang/gcc
- // on x86 but it is possible.
+ // After a mid-function epilogue we will need to re-insert the original
+ // unwind rules so unwinds work for the remainder of the function. These
+ // aren't common with clang/gcc on x86 but it is possible.
bool reinstate_unwind_state = false;
while (offset < size) {
@@ -1015,8 +1004,7 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
offset += insn_len;
m_cur_insn = data + offset;
- // offset is pointing beyond the bounds of the
- // function; stop looping.
+ // offset is pointing beyond the bounds of the function; stop looping.
if (offset >= size)
continue;
@@ -1044,9 +1032,8 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
}
if (row_id == 0) {
- // If we are here, compiler didn't generate CFI for prologue.
- // This won't happen to GCC or clang.
- // In this case, bail out directly.
+ // If we are here, compiler didn't generate CFI for prologue. This won't
+ // happen to GCC or clang. In this case, bail out directly.
return false;
}
@@ -1086,10 +1073,9 @@ bool x86AssemblyInspectionEngine::AugmentUnwindPlanFromCallSite(
}
if (pop_reg_p(regno)) {
// Technically, this might be a nonvolatile register recover in
- // epilogue.
- // We should reset RegisterInfo for the register.
- // But in practice, previous rule for the register is still valid...
- // So we ignore this case.
+ // epilogue. We should reset RegisterInfo for the register. But in
+ // practice, previous rule for the register is still valid... So we
+ // ignore this case.
row->SetOffset(offset);
row->GetCFAValue().IncOffset(-m_wordsize);