[Lldb-commits] [PATCH] D126464: [lldb] Add support to load object files from thin archives
PRESIDENT810 updated this revision to Diff 432857. PRESIDENT810 added a comment. I have refactored my code so it should looks cleaner now, but I'm not sure how to add a test. It seems that adding a test for thin archive on macOS platforms can be not so straightforward. I see that in lldb/test/API/functionalities/archives/Makefile, the test suite is using libtool instead of ar to create archives on macOS platforms, and I don't know whether I can produce a thin archive with that. Also, ld on macOS platforms seems to be unable to identify thin archives (I'm using ld64.lld when testing my code locally). I would really appreciate it if someone can provide some advice about how to implement such a test case here, thank you! CHANGES SINCE LAST ACTION https://reviews.llvm.org/D126464/new/ https://reviews.llvm.org/D126464 Files: lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h Index: lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h === --- lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -15,19 +15,24 @@ #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" +#include "llvm/Object/Archive.h" #include "llvm/Support/Chrono.h" +#include "llvm/Support/Path.h" #include #include #include +enum class ArchiveType { Invalid, Archive, ThinArchive }; + class ObjectContainerBSDArchive : public lldb_private::ObjectContainer { public: ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, -lldb::offset_t offset, lldb::offset_t length); +lldb::offset_t offset, lldb::offset_t length, +ArchiveType archive_type); ~ObjectContainerBSDArchive() override; @@ -54,7 +59,7 @@ lldb::offset_t length, lldb_private::ModuleSpecList &specs); - static bool MagicBytesMatch(const lldb_private::DataExtractor &data); + static ArchiveType MagicBytesMatch(const lldb_private::DataExtractor &data); // Member Functions bool ParseHeader() override; @@ -78,6 +83,10 @@ void Clear(); +lldb::offset_t ExtractFromThin(const lldb_private::DataExtractor &data, + lldb::offset_t offset, + llvm::StringRef stringTable); + lldb::offset_t Extract(const lldb_private::DataExtractor &data, lldb::offset_t offset); /// Object name in the archive. @@ -156,6 +165,8 @@ lldb_private::DataExtractor &GetData() { return m_data; } +ArchiveType GetArchiveType() { return m_archive_type; } + protected: typedef lldb_private::UniqueCStringMap ObjectNameToIndexMap; // Member Variables @@ -167,11 +178,14 @@ lldb_private::DataExtractor m_data; ///< The data for this object container ///so we don't lose data if the .a files ///gets modified +ArchiveType m_archive_type; }; void SetArchive(Archive::shared_ptr &archive_sp); Archive::shared_ptr m_archive_sp; + + ArchiveType m_archive_type; }; #endif // LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_BSD_ARCHIVE_OBJECTCONTAINERBSDARCHIVE_H Index: lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp === --- lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -40,6 +40,8 @@ using namespace lldb; using namespace lldb_private; +using namespace llvm::object; + LLDB_PLUGIN_DEFINE(ObjectContainerBSDArchive) ObjectContainerBSDArchive::Object::Object() : ar_name() {} @@ -55,6 +57,74 @@ file_size = 0; } +lldb::offset_t ObjectContainerBSDArchive::Object::ExtractFromThin( +const DataExtractor &data, lldb::offset_t offset, +llvm::StringRef stringTable) { + size_t ar_name_len = 0; + std::string str; + char *err; + + // File header + // + // The common format is as follows. + // + // Offset Length NameFormat + // 0 16 File name ASCII right padded with spaces (no spaces + // allowed in file name) + // 16 12 File modDecimal as cstring right padded with + // spaces + // 28 6 Owner IDDecimal as cstring right padded with + // spaces + // 34 6 Group IDDecimal as cstring right padded wi
[Lldb-commits] [PATCH] D124731: [lldb] Consider binary as module of last resort
DavidSpickett added a comment. (I also keep an eye on the bots Omair was referring to) You can just reland this change as is (revert your revert) and if something else goes wrong you'll either get a failure email or we'll let you know. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D124731/new/ https://reviews.llvm.org/D124731 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D126614: [lldb] [gdb-remote] Client support for using the non-stop protocol
mgorny updated this revision to Diff 432910. mgorny added a comment. Split the main tests into two variants: one that assumes that server runs in all-stop mode (like lldb-server), the other assuming it runs in non-stop mode (like gdbserver on Linux). CHANGES SINCE LAST ACTION https://reviews.llvm.org/D126614/new/ https://reviews.llvm.org/D126614 Files: lldb/packages/Python/lldbsuite/test/gdbclientutils.py lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td lldb/source/Target/Process.cpp lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py === --- lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py +++ lldb/test/API/functionalities/gdb_remote_client/TestGDBRemoteClient.py @@ -585,3 +585,168 @@ } self.do_siginfo_test("remote-freebsd", "basic_eh_frame.yaml", data, expected) + +def test_QNonStop_query(self): +class MyResponder(MockGDBServerResponder): +vStopped_counter = 0 + +def qSupported(self, client_supported): +return "QNonStop+;" + super().qSupported(client_supported) + +def QNonStop(self, val): +assert val == 1 +return "OK" + +def qfThreadInfo(self): +return "m10,12" + +def qsThreadInfo(self): +return "l" + +def vStopped(self): +self.vStopped_counter += 1 +return ("OK" if self.vStopped_counter % 2 == 0 +else "T00;thread:10") + +self.dbg.HandleCommand( +"settings set plugin.process.gdb-remote.use-non-stop-protocol true") +self.addTearDownHook(lambda: +self.runCmd( +"settings set plugin.process.gdb-remote.use-non-stop-protocol " +"false")) +self.server.responder = MyResponder() +target = self.dbg.CreateTarget("") +process = self.connect(target) +self.assertPacketLogContains(["QNonStop:1", "vStopped"]) + +def test_QNonStop_run(self): +class MyResponder(MockGDBServerResponder): +vStopped_counter = 0 + +def qSupported(self, client_supported): +return "QNonStop+;" + super().qSupported(client_supported) + +def QNonStop(self, val): +assert val == 1 +return "OK" + +def qfThreadInfo(self): +return "m10,12" + +def qsThreadInfo(self): +return "l" + +def vStopped(self): +self.vStopped_counter += 1 +return ("OK" if self.vStopped_counter > 1 +else "T00;thread:10") + +def cont(self): +self.vStopped_counter = 0 +return ["OK", "%Stop:T02;thread:12"] + +def vCtrlC(self): +return "OK" + +self.dbg.HandleCommand( +"settings set plugin.process.gdb-remote.use-non-stop-protocol true") +self.addTearDownHook(lambda: +self.runCmd( +"settings set plugin.process.gdb-remote.use-non-stop-protocol " +"false")) +self.server.responder = MyResponder() +target = self.dbg.CreateTarget("") +process = self.connect(target) +self.assertPacketLogContains(["QNonStop:1"]) + +process.Continue() +self.assertPacketLogContains(["vStopped", "vCtrlC"]) +self.assertEqual(process.GetSelectedThread().GetStopReason(), + lldb.eStopReasonSignal) +self.assertEqual(process.GetSelectedThread().GetStopDescription(100), + "signal SIGINT") + +def test_QNonStop_run_non_stop_server(self): +class MyResponder(MockGDBServerResponder): +def qSupported(self, client_supported): +return "QNonStop+;" + super().qSupported(client_supported) + +def QNonStop(self, val): +assert val == 1 +return "OK" + +def qfThreadInfo(self): +return "m10,12" + +def qsThreadInfo(self): +return "l" + +def vStopped(self): +return "OK" + +def cont(self): +return ["OK", "%Stop:T02;thread:12"] + +def vCtrlC(self): +return ["OK", "%Stop:T00;thread:10"]
[Lldb-commits] [PATCH] D126655: [lldb] [gdb-remote] Be more explicit about notification reading
mgorny created this revision. mgorny added reviewers: labath, krytarowski, emaste. Herald added a subscriber: arichardson. Herald added a project: All. mgorny requested review of this revision. The current GDBRemoteCommunication::ReadPacket() support for notifications is very limited. Notably, it can return notifications when the caller does not expect them and it does not provide an explicit API to distinguish them from standard packets. This is not a major problem right now, as we force serialization when running in non-stop mode and can predict when we expect notifications to arrive. Firstly, add an explicit 'allow_notification' parameter to ReadPacket() and WaitForPacketNoLock(). When it is false (the default), notifications are pushed onto a queue rather than returned to the caller. Effectively, the existing callers can now safely expect the reading functions to return only standard responses, and the non-stop logic can explicitly permit notifications. Secondly, add an explicit PacketResult value for notifications. This value can only be returned when allow_notification is true, so it does not require changes for most of the callers. For the few that support notifications, it makes it possible to distinguish standard packets from notification packets. Update the non-stop client code to take advantage of the new API, and therefore be more strict when dealing with responses in non-stop protocol mode. Sponsored by: The FreeBSD Foundation https://reviews.llvm.org/D126655 Files: lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h === --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -12,6 +12,7 @@ #include "GDBRemoteCommunicationHistory.h" #include +#include #include #include #include @@ -89,17 +90,18 @@ enum class PacketType { Invalid = 0, Standard, Notify }; enum class PacketResult { -Success = 0,// Success -ErrorSendFailed,// Status sending the packet -ErrorSendAck, // Didn't get an ack back after sending a packet -ErrorReplyFailed, // Status getting the reply -ErrorReplyTimeout, // Timed out waiting for reply -ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that -// was sent -ErrorReplyAck, // Sending reply ack failed -ErrorDisconnected, // We were disconnected -ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet -// request +Success = 0, // Success +ErrorSendFailed, // Status sending the packet +ErrorSendAck,// Didn't get an ack back after sending a packet +ErrorReplyFailed,// Status getting the reply +ErrorReplyTimeout, // Timed out waiting for reply +ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that + // was sent +ErrorReplyAck, // Sending reply ack failed +ErrorDisconnected, // We were disconnected +ErrorNoSequenceLock, // We couldn't get the sequence lock for a multi-packet + // request +Notify, // Successfully gotten a notification packet }; // Class to change the timeout for a given scope and restore it to the @@ -179,6 +181,7 @@ bool m_is_platform; // Set to true if this class represents a platform, // false if this class represents a debug session for // a single process + std::deque m_notification_packet_queue; CompressionType m_compression_type; @@ -190,7 +193,8 @@ bool skip_ack = false); PacketResult ReadPacket(StringExtractorGDBRemote &response, - Timeout timeout, bool sync_on_timeout); + Timeout timeout, bool sync_on_timeout, + bool allow_notification = false); PacketResult ReadPacketWithOutputSupport( StringExtractorGDBRemote &response, Timeout timeout, @@ -199,7 +203,8 @@ PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response, Timeout timeout, - bool sync_on_timeout); + bool sync_on_timeout, + bool allow_notification = false); bool CompressionIsEnabled() { return m_compression_type != CompressionType::None; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp === --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ lldb/s
[Lldb-commits] [PATCH] D126657: [lldb] Fix loading DLL from some ramdisk on Windows
alvinhochun created this revision. Herald added a subscriber: mstorsjo. Herald added a project: All. alvinhochun requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits. The WinAPI `GetFinalPathNameByHandle` is used to retrieve the DLL file name from the HANDLE provided to `LOAD_DLL_DEBUG_EVENT` in the debug loop. When this API fails, lldb will simply ignore that module. Certain ramdisk (e.g. ImDisk) does not work with this API, which means it is impossible to use lldb to debug a process which loads DLLs located on this type of ramdisk. In order to make this work, we need to use a fallback routine which involves creating a file mapping, using `GetMappedFileName` to get a device path, then substitutes the device path with its drive letter. References: - https://developercommunity.visualstudio.com/t/cannot-debug-program-when-compiled-to-ram-drive/43004#T-N109926 - https://github.com/jrfonseca/drmingw/issues/65 - https://docs.microsoft.com/en-us/windows/win32/memory/obtaining-a-file-name-from-a-file-handle Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D126657 Files: lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp Index: lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp === --- lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/ProcessLaunchInfo.h" #include "lldb/Host/ThreadLauncher.h" +#include "lldb/Host/windows/AutoHandle.h" #include "lldb/Host/windows/HostProcessWindows.h" #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/ProcessLauncherWindows.h" @@ -29,6 +30,8 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" +#include + #ifndef STATUS_WX86_BREAKPOINT #define STATUS_WX86_BREAKPOINT 0x401FL // For WOW64 #endif @@ -409,6 +412,60 @@ return DBG_CONTINUE; } +static llvm::Optional GetFileNameFromHandleFallback(HANDLE hFile) { + // Check that file is not empty as we cannot map a file with zero length. + DWORD dwFileSizeHi = 0; + DWORD dwFileSizeLo = ::GetFileSize(hFile, &dwFileSizeHi); + if (dwFileSizeLo == 0 && dwFileSizeHi == 0) +return llvm::None; + + AutoHandle filemap( + ::CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 1, NULL), nullptr); + if (!filemap.IsValid()) +return llvm::None; + + auto view_deleter = [](void *pMem) { ::UnmapViewOfFile(pMem); }; + std::unique_ptr pMem( + ::MapViewOfFile(filemap.get(), FILE_MAP_READ, 0, 0, 1), view_deleter); + if (!pMem) +return llvm::None; + + std::array mapped_filename; + if (!::GetMappedFileNameW(::GetCurrentProcess(), pMem.get(), +mapped_filename.data(), mapped_filename.size())) +return llvm::None; + + // A series of null-terminated strings, plus an additional null character + std::array drive_strings; + drive_strings[0] = L'\0'; + if (!::GetLogicalDriveStringsW(drive_strings.size(), drive_strings.data())) +return llvm::None; + + std::array drive = {L"_:"}; + for (auto it = drive_strings.cbegin(); *it != L'\0'; it += wcslen(it) + 1) { +// Copy the drive letter to the template string +drive[0] = it[0]; +std::array device_name; +if (::QueryDosDeviceW(drive.data(), device_name.data(), + device_name.size())) { + size_t device_name_len = wcslen(device_name.data()); + if (device_name_len < mapped_filename.size()) { +bool match = _wcsnicmp(mapped_filename.data(), device_name.data(), + device_name_len) == 0; +if (match && mapped_filename[device_name_len] == L'\\') { + // Replace device path with its drive letter + std::wstring rebuilt_path(drive.data()); + rebuilt_path.append(&mapped_filename[device_name_len]); + std::string path_utf8; + llvm::convertWideToUTF8(rebuilt_path, path_utf8); + return path_utf8; +} + } +} + } + return llvm::None; +} + DWORD DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id) { @@ -420,6 +477,17 @@ return DBG_CONTINUE; } + auto on_load_dll = [&](llvm::StringRef path) { +FileSpec file_spec(path); +ModuleSpec module_spec(file_spec); +lldb::addr_t load_addr = reinterpret_cast(info.lpBaseOfDll); + +LLDB_LOG(log, "Inferior {0} - DLL '{1}' loaded at address {2:x}...", + m_process.GetProcessId(), path, info.lpBaseOfDll); + +m_debug_delegate->OnLoadDll(module_spec, load_addr); + }; + std::vector buffer(1); DWORD required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); @@ -434,14 +502,10 @@ if (path_str.startswith("?\\")) path += 4; -FileSpec
[Lldb-commits] [PATCH] D126668: LLDB: Fix resolving nested template parameters
PatriosTheGreat created this revision. PatriosTheGreat added a reviewer: teemperor. Herald added a reviewer: shafik. Herald added a project: All. PatriosTheGreat requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits. Right now LLDB ignores nested template type: echo " template struct A {}; int main() { A> s; } " > sample.cc clang++ sample.cc -g -O0 lldb-15 a.out -o "breakpoint set -l 6 -f sample.cc" -o "run" -o "frame variable" The result: (A**>) s = {} This issue was introduced in LLDB 12 due to this CL: https://reviews.llvm.org/D92425 Before LLDB 12 this type was resolving correctly: (A** >) s = {} I discussed this issue with Raphael in discord: https://discord.com/channels/636084430946959380/636732809708306432/980825811714191371 Apparently in this case Clang emits A as a forward declaration: 0x05b4: DW_TAG_base_type DW_AT_name ("int") DW_AT_encoding (DW_ATE_signed) DW_AT_byte_size (0x04) 0x05bb: DW_TAG_structure_type DW_AT_calling_convention(DW_CC_pass_by_value) DW_AT_name ("A >") DW_AT_byte_size (0x01) DW_AT_decl_file ("/home/teemperor/test/args.cpp") DW_AT_decl_line (2) 0x05c4: DW_TAG_template_type_parameter DW_AT_type(0x05ce "A") DW_AT_name("T") 0x05cd: NULL 0x05ce: DW_TAG_structure_type DW_AT_name ("A") DW_AT_declaration (true) 0x05d3: NULL So for LLDB it looks the same as template with empty arguments. Turning back the old logic is fixing this issue. Other tests from LLVM test suite on Linux seems to be green. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D126668 Files: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py Index: lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py === --- lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py +++ lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py @@ -47,7 +47,7 @@ # Record types without a defining declaration are not complete. self.assertPointeeIncomplete("FwdClass *", "fwd_class") self.assertPointeeIncomplete("FwdClassTypedef *", "fwd_class_typedef") -self.assertPointeeIncomplete("FwdTemplateClass<> *", "fwd_template_class") +self.assertPointeeIncomplete("FwdTemplateClass *", "fwd_template_class") # A pointer type is complete even when it points to an incomplete type. fwd_class_ptr = self.expect_expr("fwd_class", result_type="FwdClass *") Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp === --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2050,6 +2050,8 @@ break; } } + if (template_param_infos.args.empty() && template_param_infos.names.empty()) +return false; return template_param_infos.args.size() == template_param_infos.names.size(); } Index: lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py === --- lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py +++ lldb/test/API/lang/cpp/complete-type-check/TestCppIsTypeComplete.py @@ -47,7 +47,7 @@ # Record types without a defining declaration are not complete. self.assertPointeeIncomplete("FwdClass *", "fwd_class") self.assertPointeeIncomplete("FwdClassTypedef *", "fwd_class_typedef") -self.assertPointeeIncomplete("FwdTemplateClass<> *", "fwd_template_class") +self.assertPointeeIncomplete("FwdTemplateClass *", "fwd_template_class") # A pointer type is complete even when it points to an incomplete type. fwd_class_ptr = self.expect_expr("fwd_class", result_type="FwdClass *") Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp === --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2050,6 +2050,8 @@ break; } } + if (template_param_infos.args.empty() && template_param_infos.names.empty()) +return false; return template_param_infos.args.size() == template_param_infos.names.size(); } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits