[Lldb-commits] [lldb] [lldb] Handle an empty SBMemoryRegionInfo from scripted process (PR #115963)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `lldb-arm-ubuntu` running on `linaro-lldb-arm-ubuntu` while building `lldb` at step 6 "test". Full details are available at: https://lab.llvm.org/buildbot/#/builders/18/builds/7002 Here is the relevant piece of the build log for the reference ``` Step 6 (test) failure: build (failure) ... UNSUPPORTED: lldb-api :: functionalities/ptrauth_diagnostics/LDRAA_error/TestPtrauthLDRAADiagnostic.py (561 of 2829) UNSUPPORTED: lldb-api :: functionalities/ptrauth_diagnostics/brkC47x_code/TestPtrauthBRKc47xDiagnostic.py (562 of 2829) UNSUPPORTED: lldb-api :: functionalities/ptrauth_diagnostics/brkC47x_x16_invalid/TestPtrauthBRKc47xX16Invalid.py (563 of 2829) PASS: lldb-api :: functionalities/rerun/TestRerun.py (564 of 2829) PASS: lldb-api :: functionalities/rerun_and_expr/TestRerunAndExpr.py (565 of 2829) UNSUPPORTED: lldb-api :: functionalities/rerun_and_expr_dylib/TestRerunAndExprDylib.py (566 of 2829) PASS: lldb-api :: functionalities/scripted_process/TestScriptedProcess.py (567 of 2829) UNSUPPORTED: lldb-api :: functionalities/scripted_process/TestStackCoreScriptedProcess.py (568 of 2829) PASS: lldb-api :: functionalities/return-value/TestReturnValue.py (569 of 2829) UNSUPPORTED: lldb-api :: functionalities/set-data/TestSetData.py (570 of 2829) FAIL: lldb-api :: functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py (571 of 2829) TEST 'lldb-api :: functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py' FAILED Script: -- /usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --arch armv8l --build-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin/dsymutil --make /usr/bin/make --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/functionalities/scripted_process_empty_memory_region -p TestScriptedProcessEmptyMemoryRegion.py -- Exit Code: 1 Command Output (stdout): -- lldb version 20.0.0git (https://github.com/llvm/llvm-project.git revision a1a1a4ced9d4ecba428175c45a24da476bdc55f4) clang revision a1a1a4ced9d4ecba428175c45a24da476bdc55f4 llvm revision a1a1a4ced9d4ecba428175c45a24da476bdc55f4 Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc'] -- Command Output (stderr): -- error: failed to launch or debug process Traceback (most recent call last): File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py", line 15, in __init__ self.threads[0] = DummyScriptedThread(self, None) File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py", line 65, in __init__ super().__init__(process, args) File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/local/lib/python3.10/dist-packages/lldb/plugins/scripted_process.py", line 273, in __init__ self.get_register_info() File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/local/lib/python3.10/dist-packages/lldb/plugins/scripted_process.py", line 364, in get_register_info raise ValueError("Unknown architecture", self.originating_process.arch) ValueError: ('Unknown architecture', 'arm') The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/llvm-project/lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py", line 108, in __lldb_init_module debugger.HandleCommand( File "/home/tcwg-buildbot/worker/lldb-arm-ubuntu/build/local/lib/python3.10/dist-packages/lldb/__init__.py", line 4878, in HandleCommand return _lldb.SBDebugger_HandleCommand(self, command) SystemError: returned a result with an exception set FAIL: LLDB (/home/tcwg-buildbot/wor
[Lldb-commits] [lldb] [lldb] Handle an empty SBMemoryRegionInfo from scripted process (PR #115963)
@@ -6184,7 +6184,14 @@ Status Process::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) { if (const lldb::ABISP &abi = GetABI()) load_addr = abi->FixAnyAddress(load_addr); - return DoGetMemoryRegionInfo(load_addr, range_info); + Status error = DoGetMemoryRegionInfo(load_addr, range_info); + // Reject a region that does not contain the requested address. + if (error.Success() && (range_info.GetRange().GetRangeBase() < load_addr || + range_info.GetRange().GetRangeEnd() <= load_addr)) jasonmolenda wrote: Ah, you did catch a mistake there, thanks. I was focusing on "lookup of 0, get back range start 0x0 size 0" and this check happens to work correctly for that, but this should be `(range_info.GetRange().GetRangeBase() < load_addr || range_info.GetRange().GetRangeEnd() >= load_addr)`. `ContainsEndInclusive` isn't correct, but the `Contains` method is, good call. https://github.com/llvm/llvm-project/pull/115963 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
https://github.com/DhruvSrivastavaX updated https://github.com/llvm/llvm-project/pull/116338 >From 0c63800bdcbadcfceed4c9a81305eda7d5a15960 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Fri, 15 Nov 2024 02:16:31 -0600 Subject: [PATCH 1/2] Added XCOFF Header Parsing --- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 126 +- .../ObjectFile/XCOFF/ObjectFileXCOFF.h| 58 2 files changed, 181 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 3be900f9a4bc9f..c06ece4347822d 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_up) return nullptr; + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) +return nullptr; + + if (!objfile_up->ParseHeader()) +return nullptr; + return objfile_up.release(); } +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) +return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), +m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { +LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); +return false; + } + + // Make sure we only handle XCOFF format. + m_binary = + llvm::unique_dyn_cast(std::move(*binary)); + if (!m_binary) +return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { @@ -136,13 +171,92 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, return XCOFFHeaderSizeFromMagic(magic) != 0; } -bool ObjectFileXCOFF::ParseHeader() { return false; } +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { +std::lock_guard guard(module_sp->GetMutex()); +lldb::offset_t offset = 0; + +if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) +ParseXCOFFOptionalHeader(m_data, &offset); +} +return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + // FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( +lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + // FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.ModuleType = data.GetU16(offset_ptr); + m_xcoff_aux_header.CpuFlag = data.GetU8(offset_ptr); + m_xcoff_aux_header.CpuType = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.DataPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.StackPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.FlagAndTDataAlignment = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextSize = data.GetU64(offset_p
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 5845688e91d85d46c0f47daaf4edfdfc772853cf 132418ff433eb684b23dcb7d6fa8374b774bb06c --extensions h,cpp -- lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h `` View the diff from clang-format here. ``diff diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index b4b1603330..dd1aea9dfc 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -200,7 +200,7 @@ bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, xcoff_header.auxhdrsize = data.GetU16(offset_ptr); xcoff_header.flags = data.GetU16(offset_ptr); xcoff_header.nsyms = data.GetU32(offset_ptr); - + return true; } @@ -239,11 +239,11 @@ bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( m_xcoff_aux_header.SecNumOfTData = data.GetU16(offset_ptr); m_xcoff_aux_header.SecNumOfTBSS = data.GetU16(offset_ptr); m_xcoff_aux_header.XCOFF64Flag = data.GetU16(offset_ptr); - + lldb::offset_t last_offset = *offset_ptr; if ((last_offset - init_offset) < m_xcoff_header.auxhdrsize) *offset_ptr += (m_xcoff_header.auxhdrsize - (last_offset - init_offset)); - + return true; } `` https://github.com/llvm/llvm-project/pull/116338 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] fda4a32 - [lldb] Only run scripted process test on x86_64/arm64
Author: Jason Molenda Date: 2024-11-15T00:56:34-08:00 New Revision: fda4a324a384af8dc57cbe0a9b6284c2e8ca073f URL: https://github.com/llvm/llvm-project/commit/fda4a324a384af8dc57cbe0a9b6284c2e8ca073f DIFF: https://github.com/llvm/llvm-project/commit/fda4a324a384af8dc57cbe0a9b6284c2e8ca073f.diff LOG: [lldb] Only run scripted process test on x86_64/arm64 The newly added test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py imports examples/python/templates/scripted_process.py which only has register definitions for x86_64 and arm64. Only run this test on those two architectures for now. Added: Modified: lldb/examples/python/templates/scripted_process.py lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py Removed: diff --git a/lldb/examples/python/templates/scripted_process.py b/lldb/examples/python/templates/scripted_process.py index b7b6499580e50c..c7d5b28b52c00a 100644 --- a/lldb/examples/python/templates/scripted_process.py +++ b/lldb/examples/python/templates/scripted_process.py @@ -5,7 +5,6 @@ class ScriptedProcess(metaclass=ABCMeta): - """ The base class for a scripted process. @@ -229,7 +228,6 @@ def create_breakpoint(self, addr, error): class ScriptedThread(metaclass=ABCMeta): - """ The base class for a scripted thread. @@ -357,7 +355,10 @@ def get_register_info(self): if self.originating_process.arch == "x86_64": self.register_info["sets"] = ["General Purpose Registers"] self.register_info["registers"] = INTEL64_GPR -elif "arm64" in self.originating_process.arch: +elif ( +"arm64" in self.originating_process.arch +or self.originating_process.arch == "aarch64" +): self.register_info["sets"] = ["General Purpose Registers"] self.register_info["registers"] = ARM64_GPR else: @@ -411,9 +412,9 @@ def __init__(self, exe_ctx, args, launched_driving_process=True): ) ) -self.threads[ -driving_thread.GetThreadID() -] = PassthroughScriptedThread(self, structured_data) +self.threads[driving_thread.GetThreadID()] = ( +PassthroughScriptedThread(self, structured_data) +) for module in self.driving_target.modules: path = module.file.fullpath @@ -507,9 +508,9 @@ def get_stop_reason(self): if self.driving_thread.GetStopReason() != lldb.eStopReasonNone: if "arm64" in self.originating_process.arch: stop_reason["type"] = lldb.eStopReasonException -stop_reason["data"][ -"desc" -] = self.driving_thread.GetStopDescription(100) +stop_reason["data"]["desc"] = ( +self.driving_thread.GetStopDescription(100) +) elif self.originating_process.arch == "x86_64": stop_reason["type"] = lldb.eStopReasonSignal stop_reason["data"]["signal"] = signal.SIGTRAP diff --git a/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py b/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py index 1ff084cfb0278e..85d7db59cba1e4 100644 --- a/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py +++ b/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py @@ -14,6 +14,9 @@ class ScriptedProcessEmptyMemoryRegion(TestBase): NO_DEBUG_INFO_TESTCASE = True +# imports examples/python/templates/scripted_process.py +# which only has register definitions for x86_64 and arm64. +@skipIf(archs=no_match(["arm64", "x86_64"])) def test_scripted_process_empty_memory_region(self): """Test that lldb handles an empty SBMemoryRegionInfo object from a scripted process plugin.""" ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Added XCOFF Object File Header Parsing (PR #116337)
https://github.com/DhruvSrivastavaX closed https://github.com/llvm/llvm-project/pull/116337 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Handle an empty SBMemoryRegionInfo from scripted process (PR #115963)
https://github.com/jasonmolenda closed https://github.com/llvm/llvm-project/pull/115963 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
https://github.com/DhruvSrivastavaX created https://github.com/llvm/llvm-project/pull/116338 This PR is in reference to porting LLDB on AIX. Link to discussions on llvm discourse and github: 1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640 2. https://github.com/llvm/llvm-project/issues/101657 The complete changes for porting are present in this draft PR: https://github.com/llvm/llvm-project/pull/102601 Added XCOFF Object File Header Parsing for AIX. This PR is an incremental PR to the base: - https://github.com/llvm/llvm-project/pull/111814 Details about XCOFF file format on AIX: [XCOFF](https://www.ibm.com/docs/en/aix/7.3?topic=formats-xcoff-object-file-format) Review Request: @labath @DavidSpickett >From 0c63800bdcbadcfceed4c9a81305eda7d5a15960 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Fri, 15 Nov 2024 02:16:31 -0600 Subject: [PATCH] Added XCOFF Header Parsing --- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 126 +- .../ObjectFile/XCOFF/ObjectFileXCOFF.h| 58 2 files changed, 181 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 3be900f9a4bc9f..c06ece4347822d 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_up) return nullptr; + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) +return nullptr; + + if (!objfile_up->ParseHeader()) +return nullptr; + return objfile_up.release(); } +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) +return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), +m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { +LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); +return false; + } + + // Make sure we only handle XCOFF format. + m_binary = + llvm::unique_dyn_cast(std::move(*binary)); + if (!m_binary) +return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { @@ -136,13 +171,92 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, return XCOFFHeaderSizeFromMagic(magic) != 0; } -bool ObjectFileXCOFF::ParseHeader() { return false; } +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { +std::lock_guard guard(module_sp->GetMutex()); +lldb::offset_t offset = 0; + +if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) +ParseXCOFFOptionalHeader(m_data, &offset); +} +return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + // FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( +lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + // FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = da
[Lldb-commits] [lldb] a1a1a4c - [lldb] Handle an empty SBMemoryRegionInfo from scripted process (#115963)
Author: Jason Molenda Date: 2024-11-15T00:26:10-08:00 New Revision: a1a1a4ced9d4ecba428175c45a24da476bdc55f4 URL: https://github.com/llvm/llvm-project/commit/a1a1a4ced9d4ecba428175c45a24da476bdc55f4 DIFF: https://github.com/llvm/llvm-project/commit/a1a1a4ced9d4ecba428175c45a24da476bdc55f4.diff LOG: [lldb] Handle an empty SBMemoryRegionInfo from scripted process (#115963) A scripted process implementation might return an SBMemoryRegionInfo object in its implementation of `get_memory_region_containing_address` which will have an address 0 and size 0, without realizing the problems this can cause. Several algorithms in lldb will try to iterate over the MemoryRegions of the process, starting at address 0 and expecting to iterate up to the highest vm address, stepping by the size of each region, so a 0-length region will result in an infinite loop. Add a check to Process::GetMemoryRegionInfo that rejects a MemoryRegion which does not contain the requested address; a 0-length memory region will therefor always be rejected. rdar://139678032 Added: lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py lldb/test/API/functionalities/scripted_process_empty_memory_region/main.c Modified: lldb/source/Target/Process.cpp Removed: diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index b99692b8a0bfd9..9125ceca74a003 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -6184,7 +6184,12 @@ Status Process::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) { if (const lldb::ABISP &abi = GetABI()) load_addr = abi->FixAnyAddress(load_addr); - return DoGetMemoryRegionInfo(load_addr, range_info); + Status error = DoGetMemoryRegionInfo(load_addr, range_info); + // Reject a region that does not contain the requested address. + if (error.Success() && !range_info.GetRange().Contains(load_addr)) +error = Status::FromErrorString("Invalid memory region"); + + return error; } Status Process::GetMemoryRegions(lldb_private::MemoryRegionInfos ®ion_list) { diff --git a/lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile b/lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py b/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py new file mode 100644 index 00..1ff084cfb0278e --- /dev/null +++ b/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py @@ -0,0 +1,33 @@ +""" +Test python scripted process which returns an empty SBMemoryRegionInfo +""" + +import os, shutil + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbtest + + +class ScriptedProcessEmptyMemoryRegion(TestBase): +NO_DEBUG_INFO_TESTCASE = True + +def test_scripted_process_empty_memory_region(self): +"""Test that lldb handles an empty SBMemoryRegionInfo object from +a scripted process plugin.""" +self.build() + +target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) +self.assertTrue(target, VALID_TARGET) + +scripted_process_example_relpath = "dummy_scripted_process.py" +self.runCmd( +"command script import " ++ os.path.join(self.getSourceDir(), scripted_process_example_relpath) +) + +self.expect("memory region 0", error=True, substrs=["Invalid memory region"]) + +self.expect("expr -- 5", substrs=["5"]) diff --git a/lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py b/lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py new file mode 100644 index 00..31e28a57122f66 --- /dev/null +++ b/lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py @@ -0,0 +1,110 @@ +import os, struct, signal + +from typing import Any, Dict + +import lldb +from lldb.plugins.scripted_process import ScriptedProcess +from lldb.plugins.scripted_process import ScriptedThread + + +class DummyScriptedProcess(ScriptedProcess): +memory = None + +def __init__(self,
[Lldb-commits] [lldb] [lldb][AIX] Added XCOFF Object File Header Parsing (PR #116337)
https://github.com/DhruvSrivastavaX created https://github.com/llvm/llvm-project/pull/116337 This PR is in reference to porting LLDB on AIX. Link to discussions on llvm discourse and github: 1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640 2. https://github.com/llvm/llvm-project/issues/101657 The complete changes for porting are present in this draft PR: https://github.com/llvm/llvm-project/pull/102601 Added XCOFF Object File Header Parsing for AIX. This PR is an incremental PR to the base: #111814 Details about XCOFF file format on AIX: [XCOFF](https://www.ibm.com/docs/en/aix/7.3?topic=formats-xcoff-object-file-format) Review Request: @labath @DavidSpickett >From 0c63800bdcbadcfceed4c9a81305eda7d5a15960 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Fri, 15 Nov 2024 02:16:31 -0600 Subject: [PATCH] Added XCOFF Header Parsing --- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 126 +- .../ObjectFile/XCOFF/ObjectFileXCOFF.h| 58 2 files changed, 181 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 3be900f9a4bc9f..c06ece4347822d 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_up) return nullptr; + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) +return nullptr; + + if (!objfile_up->ParseHeader()) +return nullptr; + return objfile_up.release(); } +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) +return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), +m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { +LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); +return false; + } + + // Make sure we only handle XCOFF format. + m_binary = + llvm::unique_dyn_cast(std::move(*binary)); + if (!m_binary) +return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { @@ -136,13 +171,92 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, return XCOFFHeaderSizeFromMagic(magic) != 0; } -bool ObjectFileXCOFF::ParseHeader() { return false; } +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { +std::lock_guard guard(module_sp->GetMutex()); +lldb::offset_t offset = 0; + +if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) +ParseXCOFFOptionalHeader(m_data, &offset); +} +return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + // FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( +lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + // FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_head
[Lldb-commits] [lldb] [lldb][AIX] Added XCOFF Object File Header Parsing (PR #116337)
https://github.com/DhruvSrivastavaX edited https://github.com/llvm/llvm-project/pull/116337 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Added XCOFF Object File Header Parsing (PR #116337)
https://github.com/DhruvSrivastavaX edited https://github.com/llvm/llvm-project/pull/116337 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
DhruvSrivastavaX wrote: Hi @labath , not sure why the `Labelling new pull requests` check failed. Also, the build check didnt automatically start for this one. https://github.com/llvm/llvm-project/pull/116338 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Make CompilerDecl::GetName (always) return template args (PR #116068)
labath wrote: > Very interesting find, I _think_ this makes sense since the `FindTypes` query > expects to find template parameters if we're looking up templates. And given > this API is used specifically to perform these kinds of queries, this LGTM. > But please confirm if my understanding is correct: > > In the non-simple names case, when we stop at the breakpoint and start > formatting the function arguments, LLDB creates a `CXXRecordDecl` with the > name `bar` in the shared library TypeSystem because it only sees a > `DW_TAG_structure_type "bar"` forward declaration without any template > parameter children DIEs. Then when we call `FindCompleteType`, the `Decl`s > `DeclarationName` would've been set to `bar`, so the `TypeQuery` will be > able to match the `bar` definition using the index. When `FindTypes` > resolves the definition DIE we get from the index, it triggers the creation > of a `ClassTemplateSpecializationDecl` in the main module's TypeSystem and > everything works out. > > But in the simple names case we create a `ClassTemplateSpecializationDecl` in > the shared library module (as opposed to a plain `CXXRecordDecl`), because > the forward declaration with `-gsimple-template-names` has a template > parameter DIE. But that declaration name is `bar`, because that's what DWARF > told us the `DeclarationName` of this `ClassTemplateSpecializationDecl` was. > But then `FindTypes` doesn't know what to do. It finds the `bar` definition > DIE from the index, but we actually end up _not_ doing a > `simple-template-names` lookup because > [UpdateCompilerContextForSimpleTemplateNames](https://github.com/llvm/llvm-project/blob/593be023615a456ca6ee0ef9bedc21301d73b73c/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp#L2816) > is only true if the query contained template parameters. That is all correct. > > So I guess my question is, why is a `TypeQuery` by basename without template > parameters not supported if we compiled with `-gsimple-template-names`? > Despite us being able to find the definition DIE in the index? I guess the > idea of `UpdateCompilerContextForSimpleTemplateNames` was to avoid doing a > double-lookup if the first `FindTypes` failed for a template basename? (I > vaguely remember this coming up on the original review) I think the problem here is of a more fundamental nature. `FindTypes` finds **types**. `bar` is *not* a type. `bar` is. So, while a type query for `bar` will find the definition DIE with `DW_AT_name="bar"`, that DIE will actually be defining the type `bar`. So when the implementation looks at the type constructed from that DIE, it will see that the name does not match what is being asked (it gets this name through a different API, so it will include the template args even without this patch), and discard the type. As far as i know, this is all WAI. Existing FindType callers expect to get a specific type as a result of their query -- not a collection of instantiations of that template. (That's definitely true in this case, where returning the collection of instantiations would just push the burden of filtering them onto the caller.) That's not to say this kind of a template search is not useful. Having something like that would go a long way towards making expressions like `(bar *) ptr` work. But that would probably be a different API and the problem is that this is basically impossible to implement in a non-simplified-template-name world, and even with simplified names, returning all instantiations might be too expensive. https://github.com/llvm/llvm-project/pull/116068 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
https://github.com/DhruvSrivastavaX updated https://github.com/llvm/llvm-project/pull/116338 >From 0c63800bdcbadcfceed4c9a81305eda7d5a15960 Mon Sep 17 00:00:00 2001 From: Dhruv-Srivastava Date: Fri, 15 Nov 2024 02:16:31 -0600 Subject: [PATCH 1/3] Added XCOFF Header Parsing --- .../ObjectFile/XCOFF/ObjectFileXCOFF.cpp | 126 +- .../ObjectFile/XCOFF/ObjectFileXCOFF.h| 58 2 files changed, 181 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 3be900f9a4bc9f..c06ece4347822d 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_up) return nullptr; + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) +return nullptr; + + if (!objfile_up->ParseHeader()) +return nullptr; + return objfile_up.release(); } +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) +return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), +m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { +LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); +return false; + } + + // Make sure we only handle XCOFF format. + m_binary = + llvm::unique_dyn_cast(std::move(*binary)); + if (!m_binary) +return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { @@ -136,13 +171,92 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, return XCOFFHeaderSizeFromMagic(magic) != 0; } -bool ObjectFileXCOFF::ParseHeader() { return false; } +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { +std::lock_guard guard(module_sp->GetMutex()); +lldb::offset_t offset = 0; + +if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) +ParseXCOFFOptionalHeader(m_data, &offset); +} +return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + // FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( +lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + // FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.ModuleType = data.GetU16(offset_ptr); + m_xcoff_aux_header.CpuFlag = data.GetU8(offset_ptr); + m_xcoff_aux_header.CpuType = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.DataPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.StackPageSize = data.GetU8(offset_ptr); + m_xcoff_aux_header.FlagAndTDataAlignment = data.GetU8(offset_ptr); + m_xcoff_aux_header.TextSize = data.GetU64(offset_p
[Lldb-commits] [lldb] [lldb] Make CompilerDecl::GetName (always) return template args (PR #116068)
Michael137 wrote: > I think the problem here is of a more fundamental nature. `FindTypes` finds > **types**. `bar` is _not_ a type. `bar` is. So, while a type query for > `bar` will find the definition DIE with `DW_AT_name="bar"`, that DIE will > actually be defining the type `bar`. So when the implementation looks at > the type constructed from that DIE, it will see that the name does not match > what is being asked (it gets this name through a different API, so it will > include the template args even without this patch), and discard the type. > > As far as i know, this is all WAI. Existing FindType callers expect to get a > specific type as a result of their query -- not a collection of > instantiations of that template. (That's definitely true in this case, where > returning the collection of instantiations would just push the burden of > filtering them onto the caller.) That's not to say this kind of a template > search is not useful. Having something like that would go a long way towards > making expressions like `(bar *) ptr` work. But that would probably be a > different API and the problem is that this is basically impossible to > implement in a non-simplified-template-name world, and even with simplified > names, returning all instantiations might be too expensive. Makes sense, thanks for elaborating LGTM The `TestDAP_evaluate.py` failure is https://github.com/llvm/llvm-project/issues/116041 (which should be fixed once you rebase) https://github.com/llvm/llvm-project/pull/116068 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Make CompilerDecl::GetName (always) return template args (PR #116068)
https://github.com/Michael137 approved this pull request. https://github.com/llvm/llvm-project/pull/116068 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
DhruvSrivastavaX wrote: > Do you actually need to parse the headers yourself? The reason for using the > llvm implementation was so that we can avoid that. FWICS, all of this data > should be available through the `(file|auxiliary)Header(32|64)` APIs. Okay, I'll take a look at that. > BTW, this is exactly the kind of granularity I was looking for. Happy to hear that! Will follow the similar practice. > I don't know, but I wouldn't be worried about that. The test failure is more > of a concern. Yeah, I think I missed the test case modification accordingly. Will update! https://github.com/llvm/llvm-project/pull/116338 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactor lldb-dap.cpp to not use global DAP variable. (PR #116272)
@@ -5046,30 +5026,48 @@ int main(int argc, char *argv[]) { pause(); } #endif + + // Initialize LLDB first before we do anything. + lldb::SBDebugger::Initialize(); + + // Terminate the debugger before the C++ destructor chain kicks in. + auto terminate_debugger = + llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); + + DAP dap = DAP(program_path.str(), default_repl_mode); ashgti wrote: I can follow up with a delete of the copy constructor https://github.com/llvm/llvm-project/pull/116272 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-da] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/ashgti created https://github.com/llvm/llvm-project/pull/116392 This refactors the port listening mode to allocate a new DAP object for each connection, allowing multiple connections to run concurrently. >From 43b8fc2a222e5460dd56782e31bd1b1ac399e03e Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 15 Nov 2024 09:56:43 -0500 Subject: [PATCH] [lldb-da] Refactoring lldb-dap port listening mode to allow multiple connections. This refactors the port listening mode to allocate a new DAP object for each connection, allowing multiple connections to run concurrently. --- .../Python/lldbsuite/test/lldbtest.py | 8 + .../test/tools/lldb-dap/dap_server.py | 75 +++- .../test/tools/lldb-dap/lldbdap_testcase.py | 32 +- lldb/test/API/tools/lldb-dap/server/Makefile | 3 + .../tools/lldb-dap/server/TestDAP_server.py | 66 lldb/test/API/tools/lldb-dap/server/main.c| 6 + lldb/tools/lldb-dap/DAP.cpp | 23 +- lldb/tools/lldb-dap/DAP.h | 50 +-- lldb/tools/lldb-dap/Options.td| 9 + lldb/tools/lldb-dap/OutputRedirector.cpp | 7 +- lldb/tools/lldb-dap/OutputRedirector.h| 12 +- lldb/tools/lldb-dap/lldb-dap.cpp | 366 ++ 12 files changed, 506 insertions(+), 151 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/server/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/server/TestDAP_server.py create mode 100644 lldb/test/API/tools/lldb-dap/server/main.c diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 8884ef5933ada8..a899854bb5ae14 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -39,6 +39,7 @@ import signal from subprocess import * import sys +import socket import time import traceback @@ -250,6 +251,13 @@ def which(program): return None +def pickrandomport(): +"""Returns a random open port.""" +with socket.socket() as sock: +sock.bind(("", 0)) +return sock.getsockname()[1] + + class ValueCheck: def __init__( self, diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index c29992ce9c7848..e4a53fe0d45907 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -903,7 +903,7 @@ def request_setBreakpoints(self, file_path, line_array, data=None): "sourceModified": False, } if line_array is not None: -args_dict["lines"] = "%s" % line_array +args_dict["lines"] = line_array breakpoints = [] for i, line in enumerate(line_array): breakpoint_data = None @@ -1154,34 +1154,38 @@ class DebugAdaptorServer(DebugCommunication): def __init__( self, executable=None, +launch=True, port=None, +unix_socket=None, init_commands=[], log_file=None, env=None, ): self.process = None -if executable is not None: -adaptor_env = os.environ.copy() -if env is not None: -adaptor_env.update(env) - -if log_file: -adaptor_env["LLDBDAP_LOG"] = log_file -self.process = subprocess.Popen( -[executable], -stdin=subprocess.PIPE, -stdout=subprocess.PIPE, -stderr=subprocess.PIPE, -env=adaptor_env, +if launch: +self.process = DebugAdaptorServer.launch( +executable, +port=port, +unix_socket=unix_socket, +log_file=log_file, +env=env, ) -DebugCommunication.__init__( -self, self.process.stdout, self.process.stdin, init_commands, log_file -) -elif port is not None: + +if port: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("127.0.0.1", port)) DebugCommunication.__init__( -self, s.makefile("r"), s.makefile("w"), init_commands +self, s.makefile("rb"), s.makefile("wb"), init_commands, log_file +) +elif unix_socket: +s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +s.connect(unix_socket) +DebugCommunication.__init__( +self, s.makefile("rb"), s.makefile("wb"), init_commands, log_file +) +else: +DebugCommunication.__init__( +self, self.process.stdout, self.process.stdin, init_commands, log_file ) def get_pid(self): @@ -1196,6 +1200,39 @@ def terminate(self):
[Lldb-commits] [lldb] [lldb-da] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/ashgti updated https://github.com/llvm/llvm-project/pull/116392 >From acfdb2da30b7a49711c3d1ec3be3c9282d6c51b4 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 15 Nov 2024 09:56:43 -0500 Subject: [PATCH] [lldb-da] Refactoring lldb-dap port listening mode to allow multiple connections. This refactors the port listening mode to allocate a new DAP object for each connection, allowing multiple connections to run concurrently. --- .../Python/lldbsuite/test/lldbtest.py | 8 + .../test/tools/lldb-dap/dap_server.py | 75 +++- .../test/tools/lldb-dap/lldbdap_testcase.py | 32 +- lldb/test/API/tools/lldb-dap/server/Makefile | 3 + .../tools/lldb-dap/server/TestDAP_server.py | 66 lldb/test/API/tools/lldb-dap/server/main.c| 6 + lldb/tools/lldb-dap/DAP.cpp | 23 +- lldb/tools/lldb-dap/DAP.h | 50 +-- lldb/tools/lldb-dap/Options.td| 9 + lldb/tools/lldb-dap/OutputRedirector.cpp | 7 +- lldb/tools/lldb-dap/OutputRedirector.h| 12 +- lldb/tools/lldb-dap/lldb-dap.cpp | 366 ++ 12 files changed, 506 insertions(+), 151 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/server/Makefile create mode 100644 lldb/test/API/tools/lldb-dap/server/TestDAP_server.py create mode 100644 lldb/test/API/tools/lldb-dap/server/main.c diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 8884ef5933ada8..a899854bb5ae14 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -39,6 +39,7 @@ import signal from subprocess import * import sys +import socket import time import traceback @@ -250,6 +251,13 @@ def which(program): return None +def pickrandomport(): +"""Returns a random open port.""" +with socket.socket() as sock: +sock.bind(("", 0)) +return sock.getsockname()[1] + + class ValueCheck: def __init__( self, diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index c29992ce9c7848..e4a53fe0d45907 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -903,7 +903,7 @@ def request_setBreakpoints(self, file_path, line_array, data=None): "sourceModified": False, } if line_array is not None: -args_dict["lines"] = "%s" % line_array +args_dict["lines"] = line_array breakpoints = [] for i, line in enumerate(line_array): breakpoint_data = None @@ -1154,34 +1154,38 @@ class DebugAdaptorServer(DebugCommunication): def __init__( self, executable=None, +launch=True, port=None, +unix_socket=None, init_commands=[], log_file=None, env=None, ): self.process = None -if executable is not None: -adaptor_env = os.environ.copy() -if env is not None: -adaptor_env.update(env) - -if log_file: -adaptor_env["LLDBDAP_LOG"] = log_file -self.process = subprocess.Popen( -[executable], -stdin=subprocess.PIPE, -stdout=subprocess.PIPE, -stderr=subprocess.PIPE, -env=adaptor_env, +if launch: +self.process = DebugAdaptorServer.launch( +executable, +port=port, +unix_socket=unix_socket, +log_file=log_file, +env=env, ) -DebugCommunication.__init__( -self, self.process.stdout, self.process.stdin, init_commands, log_file -) -elif port is not None: + +if port: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("127.0.0.1", port)) DebugCommunication.__init__( -self, s.makefile("r"), s.makefile("w"), init_commands +self, s.makefile("rb"), s.makefile("wb"), init_commands, log_file +) +elif unix_socket: +s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +s.connect(unix_socket) +DebugCommunication.__init__( +self, s.makefile("rb"), s.makefile("wb"), init_commands, log_file +) +else: +DebugCommunication.__init__( +self, self.process.stdout, self.process.stdin, init_commands, log_file ) def get_pid(self): @@ -1196,6 +1200,39 @@ def terminate(self): self.process.wait() self.process = None +@classmethod +def launch( +cls, executable: str, /, port=None, u
[Lldb-commits] [lldb] [lldb-da] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/ashgti ready_for_review https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-da] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 0fb8fac5d6c10610574e6e472670823eaff0c949 acfdb2da30b7a49711c3d1ec3be3c9282d6c51b4 --extensions h,c,cpp -- lldb/test/API/tools/lldb-dap/server/main.c lldb/tools/lldb-dap/DAP.cpp lldb/tools/lldb-dap/DAP.h lldb/tools/lldb-dap/OutputRedirector.cpp lldb/tools/lldb-dap/OutputRedirector.h lldb/tools/lldb-dap/lldb-dap.cpp `` View the diff from clang-format here. ``diff diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 8998036fbe..a1e4159965 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -34,8 +34,8 @@ namespace lldb_dap { DAP::DAP(llvm::StringRef path, std::shared_ptr log, ReplMode repl_mode, std::vector pre_init_commands) -: debug_adaptor_path(path), broadcaster("lldb-dap"), - log(log), exception_breakpoints(), pre_init_commands(pre_init_commands), +: debug_adaptor_path(path), broadcaster("lldb-dap"), log(log), + exception_breakpoints(), pre_init_commands(pre_init_commands), focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false), is_attach(false), enable_auto_variable_summaries(false), enable_synthetic_child_debugging(false), `` https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix regex support in SBTarget.modules_access (PR #116452)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Dave Lee (kastiglione) Changes First, `SRE_Pattern` does not exist on newer Python's, use `type(re.compile(''))` like other Python extensions do. The dynamic type is because some earlier versions of Python 3 do not have `re.Pattern`. Second, `SBModule` has a `file` property, not a `path` property. --- Full diff: https://github.com/llvm/llvm-project/pull/116452.diff 2 Files Affected: - (modified) lldb/bindings/interface/SBTargetExtensions.i (+2-2) - (modified) lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py (+6-9) ``diff diff --git a/lldb/bindings/interface/SBTargetExtensions.i b/lldb/bindings/interface/SBTargetExtensions.i index d756a351a810ab..43125d8970615b 100644 --- a/lldb/bindings/interface/SBTargetExtensions.i +++ b/lldb/bindings/interface/SBTargetExtensions.i @@ -79,11 +79,11 @@ STRING_EXTENSION_LEVEL_OUTSIDE(SBTarget, lldb::eDescriptionLevelBrief) module = self.sbtarget.GetModuleAtIndex(idx) if module.uuid == key: return module -elif type(key) is re.SRE_Pattern: +elif isinstance(key, type(re.compile(''))): matching_modules = [] for idx in range(num_modules): module = self.sbtarget.GetModuleAtIndex(idx) -re_match = key.search(module.path.fullpath) +re_match = key.search(module.file.fullpath) if re_match: matching_modules.append(module) return matching_modules diff --git a/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py b/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py index 06f338b3ed1ded..bcf8735c7c3f98 100644 --- a/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py +++ b/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py @@ -3,6 +3,7 @@ """ import os +import re import lldb from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil @@ -30,15 +31,11 @@ def test_stdcxx_disasm(self): self.runCmd("disassemble -n '%s'" % function.GetName()) lib_stdcxx = "FAILHORRIBLYHERE" -# Iterate through the available modules, looking for stdc++ library... -for i in range(target.GetNumModules()): -module = target.GetModuleAtIndex(i) -fs = module.GetFileSpec() -if fs.GetFilename().startswith("libstdc++") or fs.GetFilename().startswith( -"libc++" -): -lib_stdcxx = str(fs) -break +# Find the stdc++ library... +stdlib_regex = re.compile(r"/lib(std)?c\+\+") +for module in target.module[stdlib_regex]: +lib_stdcxx = module.file.fullpath +break # At this point, lib_stdcxx is the full path to the stdc++ library and # module is the corresponding SBModule. `` https://github.com/llvm/llvm-project/pull/116452 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix regex support in SBTarget.modules_access (PR #116452)
https://github.com/kastiglione edited https://github.com/llvm/llvm-project/pull/116452 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Improve editline completion formatting (PR #116456)
https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/116456 This patch improves the formatting of editline completions. The current implementation is naive and doesn't account for the terminal width. Concretely, the old implementation suffered from the following issues: - We would unconditionally pad to the longest completion. If that completion exceeds the width of the terminal, that would result in a lot of superfluous white space and line wrapping. - When printing the description, we wouldn't account for the presence of newlines, and they would continue without leading padding. The new code accounts for both. If the completion exceeds the available terminal width, we show what fits on the current lined followed by ellipsis. We also no longer pad beyond the length of the current line. Finally, we print the description line by line, with the proper leading padding. If a line of the description exceeds the available terminal width, we print ellipsis and won't print the next line. Before: ``` Available completions: _regexp-attach-- Attach to process by ID or name. _regexp-break -- Set a breakpoint using one of several shorthand formats. _regexp-bt-- Show backtrace of the current thread's call sta ck. Any numeric argument displays at most that many frames. The argument 'al l' displays all threads. Use 'settings set frame-format' to customize the pr inting of individual frames and 'settings set thread-format' to customize th e thread header. Frame recognizers may filter thelist. Use 'thread backtrace -u (--unfiltered)' to see them all. _regexp-display -- Evaluate an expression at every stop (see 'help target stop-hook'.) ``` After: ``` Available completions: _regexp-attach-- Attach to process by ID or name. _regexp-break -- Set a breakpoint using one of several shorth... _regexp-bt-- Show backtrace of the current thread's call ... _regexp-display -- Evaluate an expression at every stop (see 'h... ``` rdar://135818198 >From a694405bd2e1b8cc96183c2f406dddbb8555cd51 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 15 Nov 2024 16:06:47 -0800 Subject: [PATCH] [lldb] Improve editline completion formatting This patch improves the formatting of editline completions. The current implementation is naive and doesn't account for the terminal width. Concretely, the old implementation suffered from the following issues: - We would unconditionally pad to the longest completion. If that completion exceeds the width of the terminal, that would result in a lot of superfluous white space and line wrapping. - When printing the description, we wouldn't account for the presence of newlines, and they would continue without leading padding. The new code accounts for both. If the completion exceeds the available terminal width, we show what fits on the current lined followed by ellipsis. We also no longer pad beyond the length of the current line. Finally, we print the description line by line, with the proper leading padding. If a line of the description exceeds the available terminal width, we print ellipsis and won't print the next line. Before: ``` Available completions: _regexp-attach-- Attach to process by ID or name. _regexp-break -- Set a breakpoint using one of several shorthand formats. _regexp-bt-- Show backtrace of the current thread's call sta ck. Any numeric argument displays at most that many frames. The argument 'al l' displays all threads. Use 'settings set frame-format' to customize the pr inting of individual frames and 'settings set thread-format' to customize th e thread header. Frame recognizers may filter thelist. Use 'thread backtrace -u (--unfiltered)' to see them all. _regexp-display -- Evaluate an expression at every stop (see 'help target stop-hook'.) ``` After: ``` Available completions: _regexp-attach-- Attach to process by ID or name. _regexp-break -- Set a breakpoint using one of several shorth... _regexp-bt-- Show backtrace of the current thread's call ... _regexp-display -- Evaluate an expression at every stop (see 'h... ``` rdar://135818198 --- lldb/include/lldb/Host/Editline.h| 2 + lldb/source/Host/common/Editline.cpp | 96 ++-- 2 files changed, 91 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h index 57e2c831e3499d..e8e8a6c0d4f67e 100644 --- a/lldb/include/lldb/Host/Editline.h +++ b/lldb/include/lldb/Host/Editline.h @@ -238,6 +238,8 @@ class Editline { /// Convert the current input lines into a UTF8 StringList StringList GetInputAsStringList(int line_count = UINT32_MAX); + size_t GetTerminalWidth() { return m_terminal_width; } + private: /// Sets the lowest line number for multi-line editing sessions.
[Lldb-commits] [lldb] [lldb] Improve editline completion formatting (PR #116456)
https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/116456 >From 3434c7de701e4851b4eefe25f23e49d415ba4dd3 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 15 Nov 2024 16:06:47 -0800 Subject: [PATCH] [lldb] Improve editline completion formatting This patch improves the formatting of editline completions. The current implementation is naive and doesn't account for the terminal width. Concretely, the old implementation suffered from the following issues: - We would unconditionally pad to the longest completion. If that completion exceeds the width of the terminal, that would result in a lot of superfluous white space and line wrapping. - When printing the description, we wouldn't account for the presence of newlines, and they would continue without leading padding. The new code accounts for both. If the completion exceeds the available terminal width, we show what fits on the current lined followed by ellipsis. We also no longer pad beyond the length of the current line. Finally, we print the description line by line, with the proper leading padding. If a line of the description exceeds the available terminal width, we print ellipsis and won't print the next line. Before: ``` Available completions: _regexp-attach-- Attach to process by ID or name. _regexp-break -- Set a breakpoint using one of several shorthand formats. _regexp-bt-- Show backtrace of the current thread's call sta ck. Any numeric argument displays at most that many frames. The argument 'al l' displays all threads. Use 'settings set frame-format' to customize the pr inting of individual frames and 'settings set thread-format' to customize th e thread header. Frame recognizers may filter thelist. Use 'thread backtrace -u (--unfiltered)' to see them all. _regexp-display -- Evaluate an expression at every stop (see 'help target stop-hook'.) ``` After: ``` Available completions: _regexp-attach-- Attach to process by ID or name. _regexp-break -- Set a breakpoint using one of several shorth... _regexp-bt-- Show backtrace of the current thread's call ... _regexp-display -- Evaluate an expression at every stop (see 'h... ``` rdar://135818198 --- lldb/include/lldb/Host/Editline.h| 2 + lldb/source/Host/common/Editline.cpp | 95 ++-- 2 files changed, 90 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h index 57e2c831e3499d..e8e8a6c0d4f67e 100644 --- a/lldb/include/lldb/Host/Editline.h +++ b/lldb/include/lldb/Host/Editline.h @@ -238,6 +238,8 @@ class Editline { /// Convert the current input lines into a UTF8 StringList StringList GetInputAsStringList(int line_count = UINT32_MAX); + size_t GetTerminalWidth() { return m_terminal_width; } + private: /// Sets the lowest line number for multi-line editing sessions. A value of /// zero suppresses line number printing in the prompt. diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index f95f854c5f220c..109cc897b853f3 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -927,12 +927,92 @@ unsigned char Editline::BufferEndCommand(int ch) { static void PrintCompletion(FILE *output_file, llvm::ArrayRef results, -size_t max_len) { +size_t max_completion_length, size_t max_lenght) { + + constexpr size_t ellipsis_length = 3; + constexpr size_t tab_legnth = 8; + constexpr size_t separator_length = 4; + const size_t description_col = + std::min(max_completion_length + tab_legnth, max_lenght); + for (const CompletionResult::Completion &c : results) { -fprintf(output_file, "\t%-*s", (int)max_len, c.GetCompletion().c_str()); -if (!c.GetDescription().empty()) - fprintf(output_file, " -- %s", c.GetDescription().c_str()); -fprintf(output_file, "\n"); +// Print the leading tab-sized padding. +fprintf(output_file, ""); +size_t cursor = tab_legnth; + +if (!c.GetCompletion().empty()) { + const size_t completion_length = c.GetCompletion().size(); + if (cursor + completion_length < max_lenght) { +fprintf(output_file, "%s", c.GetCompletion().c_str()); +cursor = cursor + completion_length; + } else { +// If the completion doesn't fit on the screen, print ellipsis and don't +// bother with the description. +fprintf(output_file, "%s...\n", +c.GetCompletion() +.substr(0, max_lenght - cursor - ellipsis_length) +.c_str()); +continue; + } +} + +if (!c.GetDescription().empty()) { + // If we have a description, we need at least 4 columns for the separator. + if (cursor + separator_length < max_lenght) { +// Add padding before the sep
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
jimingham wrote: Ah, right. The one place where a ThreadPlan should be messing with the ThreadPlanStack (through its Thread) is ThreadPlan::DidPush. The point of that is largely that thread plans can't push new thread plans on the stack in their constructor - since they aren't on the stack yet. However there are plans that work by delegating so they need to push the delegate plan before getting asked any questions. That's what DidPush is for. https://github.com/llvm/llvm-project/pull/116438 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/vogelsgesang edited https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -137,42 +141,232 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) { } } -SOCKET AcceptConnection(DAP &dap, int portno) { - // Accept a socket connection from any host on "portno". - SOCKET newsockfd = -1; - struct sockaddr_in serv_addr, cli_addr; +/// Redirect stdout and stderr fo the IDE's console output. +/// +/// Errors in this operation will be printed to the log file and the IDE's +/// console output as well. +/// +/// \return +/// A fd pointing to the original stdout. +void SetupRedirection(DAP &dap, int stdoutfd = -1, int stderrfd = -1) { vogelsgesang wrote: what is the intended behavior here if we have multiple DAP connections running in parallel? Should the `stdin` be redirected to all of them? Only the latest one? Only the first one? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add logging for missing `.dwo` files (PR #116436)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Adrian Vogelsgesang (vogelsgesang) Changes I had a hard time to debug a `dwo` file whose file was not found. This log message would have saved me a lot of time. --- Full diff: https://github.com/llvm/llvm-project/pull/116436.diff 1 Files Affected: - (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+8) ``diff diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 666595a6d0635f..2bb41903beb3b4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1963,6 +1963,14 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( "{1:x16}", error_dwo_path.GetPath().c_str(), cu_die.GetOffset())); +if (Log *log = GetLog(LLDBLog::Symbols)) { + GetObjectFile()->GetModule()->LogMessage( + log, + "unable to locate .dwo debug file \"{0}\" for skeleton DIE " + "{1:x16}", + error_dwo_path.GetPath().c_str(), unit.GetOffset()); +} + if (m_dwo_warning_issued.test_and_set(std::memory_order_relaxed) == false) { GetObjectFile()->GetModule()->ReportWarning( "unable to locate separate debug file (dwo, dwp). Debugging will be " `` https://github.com/llvm/llvm-project/pull/116436 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
https://github.com/JDevlieghere edited https://github.com/llvm/llvm-project/pull/116438 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix regex support in SBTarget.modules_access (PR #116452)
https://github.com/kastiglione created https://github.com/llvm/llvm-project/pull/116452 First, `SRE_Pattern` does not exist on newer Python's, use `type(re.compile(''))` like other Python extensions do. The dynamic type is because some earlier versions of Python 3 do not have `re.Pattern`. Second, `SBModule` has a `file` property, not a `path` property. >From 5379412f53352acafd75575d8b54806050de535d Mon Sep 17 00:00:00 2001 From: Dave Lee Date: Fri, 15 Nov 2024 15:24:44 -0800 Subject: [PATCH] [lldb] Fix regex support in SBTarget.modules_access First, `SRE_Pattern` does not exist on newer Python's, use `type(re.compile(''))` like other Python extensions do. The dynamic type is because some earlier versions of Python 3 do not have `re.Pattern`. Second, `SBModule` has a `file` property, not a `path` property. --- lldb/bindings/interface/SBTargetExtensions.i | 4 ++-- .../API/lang/cpp/stl/TestStdCXXDisassembly.py | 15 ++- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/lldb/bindings/interface/SBTargetExtensions.i b/lldb/bindings/interface/SBTargetExtensions.i index d756a351a810ab..43125d8970615b 100644 --- a/lldb/bindings/interface/SBTargetExtensions.i +++ b/lldb/bindings/interface/SBTargetExtensions.i @@ -79,11 +79,11 @@ STRING_EXTENSION_LEVEL_OUTSIDE(SBTarget, lldb::eDescriptionLevelBrief) module = self.sbtarget.GetModuleAtIndex(idx) if module.uuid == key: return module -elif type(key) is re.SRE_Pattern: +elif isinstance(key, type(re.compile(''))): matching_modules = [] for idx in range(num_modules): module = self.sbtarget.GetModuleAtIndex(idx) -re_match = key.search(module.path.fullpath) +re_match = key.search(module.file.fullpath) if re_match: matching_modules.append(module) return matching_modules diff --git a/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py b/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py index 06f338b3ed1ded..bcf8735c7c3f98 100644 --- a/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py +++ b/lldb/test/API/lang/cpp/stl/TestStdCXXDisassembly.py @@ -3,6 +3,7 @@ """ import os +import re import lldb from lldbsuite.test.lldbtest import * import lldbsuite.test.lldbutil as lldbutil @@ -30,15 +31,11 @@ def test_stdcxx_disasm(self): self.runCmd("disassemble -n '%s'" % function.GetName()) lib_stdcxx = "FAILHORRIBLYHERE" -# Iterate through the available modules, looking for stdc++ library... -for i in range(target.GetNumModules()): -module = target.GetModuleAtIndex(i) -fs = module.GetFileSpec() -if fs.GetFilename().startswith("libstdc++") or fs.GetFilename().startswith( -"libc++" -): -lib_stdcxx = str(fs) -break +# Find the stdc++ library... +stdlib_regex = re.compile(r"/lib(std)?c\+\+") +for module in target.module[stdlib_regex]: +lib_stdcxx = module.file.fullpath +break # At this point, lib_stdcxx is the full path to the stdc++ library and # module is the corresponding SBModule. ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix regex support in SBTarget.modules_access (PR #116452)
@@ -79,11 +79,11 @@ STRING_EXTENSION_LEVEL_OUTSIDE(SBTarget, lldb::eDescriptionLevelBrief) module = self.sbtarget.GetModuleAtIndex(idx) if module.uuid == key: return module -elif type(key) is re.SRE_Pattern: +elif isinstance(key, type(re.compile(''))): matching_modules = [] for idx in range(num_modules): module = self.sbtarget.GetModuleAtIndex(idx) -re_match = key.search(module.path.fullpath) +re_match = key.search(module.file.fullpath) kastiglione wrote: Since this was broken, and obviously not used, I'd like to also change this from `fullpath` to `basename`. Opinions? https://github.com/llvm/llvm-project/pull/116452 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -22,8 +22,17 @@ def port: S<"port">, HelpText<"Communicate with the lldb-dap tool over the defined port.">; def: Separate<["-"], "p">, Alias, + MetaVarName<"">, HelpText<"Alias for --port">; +def unix_socket: S<"unix-socket">, + MetaVarName<"">, + HelpText<"Communicate with the lldb-dap tool over the unix socket or named pipe.">; +def: Separate<["-"], "u">, vogelsgesang wrote: ```suggestion def: Separate<["-"], "s">, ``` (assuming we rename `unix_socket` to `socket`) https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Convert file address to load address when reading memory for DW_OP_piece (PR #116411)
https://github.com/kuilpd created https://github.com/llvm/llvm-project/pull/116411 When parsing an optimized value and reading a piece from a file address, LLDB tries to read the data from memory using that address. This patch converts file address to load address before reading the memory. Fixes #111313 #97484 >From 37f9b0f2388349bbf74e1225391efd61c55f756c Mon Sep 17 00:00:00 2001 From: Ilia Kuklin Date: Thu, 14 Nov 2024 20:15:19 +0500 Subject: [PATCH 1/2] Convert file address to load address when reading memory for DW_OP_piece --- lldb/source/Expression/DWARFExpression.cpp | 19 --- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index f92f25ed342a9c..a7126b25c1cc38 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -1853,12 +1853,25 @@ llvm::Expected DWARFExpression::Evaluate( const Value::ValueType curr_piece_source_value_type = curr_piece_source_value.GetValueType(); Scalar &scalar = curr_piece_source_value.GetScalar(); - const lldb::addr_t addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); + lldb::addr_t addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); switch (curr_piece_source_value_type) { case Value::ValueType::Invalid: return llvm::createStringError("invalid value type"); - case Value::ValueType::LoadAddress: - case Value::ValueType::FileAddress: { + case Value::ValueType::FileAddress: +if (target) { + curr_piece_source_value.ConvertToLoadAddress(module_sp.get(), + target); + addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); +} else { + return llvm::createStringError( + "unable to convert file address 0x%" PRIx64 + " to load address " + "for DW_OP_piece(%" PRIu64 "): " + "no target available", + addr, piece_byte_size); +} +[[fallthrough]]; + case Value::ValueType::LoadAddress: { if (target) { if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) { if (target->ReadMemory(addr, curr_piece.GetBuffer().GetBytes(), >From 86c66f7084fb35371e057388d4edc50790c1c6b8 Mon Sep 17 00:00:00 2001 From: Ilia Kuklin Date: Fri, 15 Nov 2024 20:42:58 +0500 Subject: [PATCH 2/2] Add a test --- .../Shell/SymbolFile/DWARF/DW_OP_piece-O3.c | 23 +++ 1 file changed, 23 insertions(+) create mode 100644 lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c diff --git a/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c b/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c new file mode 100644 index 00..d31250426dc112 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c @@ -0,0 +1,23 @@ +// Check that optimized with -O3 values that have a file address can be read +// DWARF info: +// 0x0023: DW_TAG_variable +// DW_AT_name ("array") +// DW_AT_type (0x0032 "char[5]") +// DW_AT_location (DW_OP_piece 0x2, DW_OP_addrx 0x0, DW_OP_piece 0x1) + +// RUN: %clang_host -O3 -gdwarf %s -o %t +// RUN: %lldb %t \ +// RUN: -o "b 22" \ +// RUN: -o "r" \ +// RUN: -o "p/x array[2]" \ +// RUN: -b | FileCheck %s +// +// CHECK: (lldb) p/x array[2] +// CHECK: (char) 0x03 + +static char array[5] = {0, 1, 2, 3, 4}; + +int main(void) { + array[2]++; + return 0; +} \ No newline at end of file ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Convert file address to load address when reading memory for DW_OP_piece (PR #116411)
https://github.com/kuilpd edited https://github.com/llvm/llvm-project/pull/116411 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -22,8 +22,17 @@ def port: S<"port">, HelpText<"Communicate with the lldb-dap tool over the defined port.">; def: Separate<["-"], "p">, Alias, + MetaVarName<"">, HelpText<"Alias for --port">; +def unix_socket: S<"unix-socket">, + MetaVarName<"">, + HelpText<"Communicate with the lldb-dap tool over the unix socket or named pipe.">; vogelsgesang wrote: should we maybe name this `socket` instead of `unix-socket`? As it apparently also support Windows named pipes, which are not UNIX? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -137,42 +141,232 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) { } } -SOCKET AcceptConnection(DAP &dap, int portno) { - // Accept a socket connection from any host on "portno". - SOCKET newsockfd = -1; - struct sockaddr_in serv_addr, cli_addr; +/// Redirect stdout and stderr fo the IDE's console output. +/// +/// Errors in this operation will be printed to the log file and the IDE's +/// console output as well. +/// +/// \return +/// A fd pointing to the original stdout. +void SetupRedirection(DAP &dap, int stdoutfd = -1, int stderrfd = -1) { vogelsgesang wrote: should this be a member function of the `DAP` class? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -140,13 +137,16 @@ struct DAP { llvm::StringRef debug_adaptor_path; InputStream input; OutputStream output; + lldb::SBFile in; + lldb::SBFile out; + lldb::SBFile err; lldb::SBDebugger debugger; lldb::SBTarget target; Variables variables; lldb::SBBroadcaster broadcaster; std::thread event_thread; std::thread progress_event_thread; - std::unique_ptr log; + std::shared_ptr log; vogelsgesang wrote: should this be a `shared_ptr`? Afaict a reference should be sufficient, given that the log file is global and will always outlive the `DAP` instances https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -22,8 +22,17 @@ def port: S<"port">, HelpText<"Communicate with the lldb-dap tool over the defined port.">; def: Separate<["-"], "p">, Alias, + MetaVarName<"">, HelpText<"Alias for --port">; +def unix_socket: S<"unix-socket">, + MetaVarName<"">, + HelpText<"Communicate with the lldb-dap tool over the unix socket or named pipe.">; +def: Separate<["-"], "u">, + Alias, + MetaVarName<"">, + HelpText<"Alias for --unix_socket">; vogelsgesang wrote: ```suggestion HelpText<"Alias for --unix-socket">; ``` afaict, the above entry calls it `unix-socket`, not `unix_socket`? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -0,0 +1,6 @@ +#include + +int main(int argc, char const *argv[]) { + printf("hello world!\n"); // breakpoint 1 + return 0; +} vogelsgesang wrote: missing trailing new line (afaik, we are using UNIX conventions, not Windows conventions?) https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -137,42 +141,232 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) { } } -SOCKET AcceptConnection(DAP &dap, int portno) { - // Accept a socket connection from any host on "portno". - SOCKET newsockfd = -1; - struct sockaddr_in serv_addr, cli_addr; +/// Redirect stdout and stderr fo the IDE's console output. +/// +/// Errors in this operation will be printed to the log file and the IDE's +/// console output as well. +/// +/// \return +/// A fd pointing to the original stdout. +void SetupRedirection(DAP &dap, int stdoutfd = -1, int stderrfd = -1) { + auto output_callback_stderr = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stderr, data); + }; + auto output_callback_stdout = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stdout, data); + }; + + llvm::Expected new_stdout_fd = + RedirectFd(stdoutfd, output_callback_stdout); + if (auto err = new_stdout_fd.takeError()) { +std::string error_message = llvm::toString(std::move(err)); +if (dap.log) + *dap.log << error_message << std::endl; +output_callback_stderr(error_message); + } + dap.out = lldb::SBFile(new_stdout_fd.get(), "w", false); + + llvm::Expected new_stderr_fd = + RedirectFd(stderrfd, output_callback_stderr); + if (auto err = new_stderr_fd.takeError()) { +std::string error_message = llvm::toString(std::move(err)); +if (dap.log) + *dap.log << error_message << std::endl; +output_callback_stderr(error_message); + } + dap.err = lldb::SBFile(new_stderr_fd.get(), "w", false); vogelsgesang wrote: in the `else` branch? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -116,6 +118,8 @@ enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch }; /// Page size used for reporting addtional frames in the 'stackTrace' request. constexpr int StackPageSize = 20; +void RegisterRequestCallbacks(DAP &dap); vogelsgesang wrote: seems to be never implemented and never called? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
https://github.com/vogelsgesang edited https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -137,42 +141,232 @@ lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) { } } -SOCKET AcceptConnection(DAP &dap, int portno) { - // Accept a socket connection from any host on "portno". - SOCKET newsockfd = -1; - struct sockaddr_in serv_addr, cli_addr; +/// Redirect stdout and stderr fo the IDE's console output. +/// +/// Errors in this operation will be printed to the log file and the IDE's +/// console output as well. +/// +/// \return +/// A fd pointing to the original stdout. +void SetupRedirection(DAP &dap, int stdoutfd = -1, int stderrfd = -1) { + auto output_callback_stderr = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stderr, data); + }; + auto output_callback_stdout = [&dap](llvm::StringRef data) { +dap.SendOutput(OutputType::Stdout, data); + }; + + llvm::Expected new_stdout_fd = + RedirectFd(stdoutfd, output_callback_stdout); + if (auto err = new_stdout_fd.takeError()) { +std::string error_message = llvm::toString(std::move(err)); +if (dap.log) + *dap.log << error_message << std::endl; +output_callback_stderr(error_message); + } + dap.out = lldb::SBFile(new_stdout_fd.get(), "w", false); vogelsgesang wrote: shouldn't this be in the `else` branch of `takeError`? What is the intended behavior here in case the redirection failed? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 4d4024e1edf354113e8d0d11661d466ae5b0bee7 943bad7a8faa41d21651de765858dbb49584547c --extensions cpp,h -- lldb/include/lldb/Target/ThreadPlanStack.h lldb/source/Target/ThreadPlanStack.cpp `` View the diff from clang-format here. ``diff diff --git a/lldb/include/lldb/Target/ThreadPlanStack.h b/lldb/include/lldb/Target/ThreadPlanStack.h index cd606bd0bb..e0f8104de9 100644 --- a/lldb/include/lldb/Target/ThreadPlanStack.h +++ b/lldb/include/lldb/Target/ThreadPlanStack.h @@ -98,12 +98,12 @@ public: void ClearThreadCache(); private: - lldb::ThreadPlanSP DiscardPlanNoLock(); lldb::ThreadPlanSP GetCurrentPlanNoLock() const; void PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, - const PlanStack &stack, lldb::DescriptionLevel desc_level, - bool include_internal) const; + const PlanStack &stack, + lldb::DescriptionLevel desc_level, + bool include_internal) const; PlanStack m_plans; ///< The stack of plans this thread is executing. PlanStack m_completed_plans; ///< Plans that have been completed by this diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp index 81fcb09b56..93a3d41142 100644 --- a/lldb/source/Target/ThreadPlanStack.cpp +++ b/lldb/source/Target/ThreadPlanStack.cpp @@ -41,18 +41,19 @@ void ThreadPlanStack::DumpThreadPlans(Stream &s, bool include_internal) const { llvm::sys::ScopedReader guard(m_stack_mutex); s.IndentMore(); - PrintOneStackNoLock(s, "Active plan stack", m_plans, desc_level, include_internal); + PrintOneStackNoLock(s, "Active plan stack", m_plans, desc_level, + include_internal); PrintOneStackNoLock(s, "Completed plan stack", m_completed_plans, desc_level, -include_internal); + include_internal); PrintOneStackNoLock(s, "Discarded plan stack", m_discarded_plans, desc_level, -include_internal); + include_internal); s.IndentLess(); } void ThreadPlanStack::PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, -const PlanStack &stack, -lldb::DescriptionLevel desc_level, -bool include_internal) const { + const PlanStack &stack, + lldb::DescriptionLevel desc_level, + bool include_internal) const { // If the stack is empty, just exit: if (stack.empty()) return; `` https://github.com/llvm/llvm-project/pull/116438 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
jimingham wrote: That is a "resource deadlock detected" error, so presumably we are managing to recursively use this ThreadPlanStack lock. I'm a bit confused that none of the stacks printed actually show any ThreadPlanStack functions on the stack??? https://github.com/llvm/llvm-project/pull/116438 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Fix regex support in SBTarget.modules_access (PR #116452)
https://github.com/kastiglione edited https://github.com/llvm/llvm-project/pull/116452 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Convert file address to load address when reading memory for DW_OP_piece (PR #116411)
https://github.com/adrian-prantl approved this pull request. This looks plausible. I wish we had just one place where we read from an address so this logic isn't duplicated all over the interpreter. https://github.com/llvm/llvm-project/pull/116411 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
@@ -179,55 +142,34 @@ Status MainLoopPosix::RunImpl::Poll() { read_fds.push_back(pfd); } - if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 && + if (ppoll(read_fds.data(), read_fds.size(), +/*timeout=*/nullptr, labath wrote: I don't see what that would solve. The goal is to sleep until one of the FDs is readable. If none of them is, the only thing we can do is go back to sleep. Sure, we can have a bug where we e.g. somehow fail to notify the pipe about a signal, but that can also happen with a spurious wakeup (cause then you have to check if the signal really occurred, and maybe the bug is that you forgot to set that flag). FWIW, there will be a timeout here after #112895 (but there is still the possibility of an infinite wait if/when there are no scheduled callbacks). https://github.com/llvm/llvm-project/pull/115197 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
@@ -384,6 +313,21 @@ void MainLoopPosix::ProcessReadObject(IOObject::WaitableHandle handle) { it->second(*this); // Do the work } +void MainLoopPosix::ProcessSignals() { + std::vector signals; labath wrote: It's the type that the OS signal APIs use. I think it's best to stick with that even though the values would technically fit into a `uint8_t`. https://github.com/llvm/llvm-project/pull/115197 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Handle an empty SBMemoryRegionInfo from scripted process (PR #115963)
https://github.com/jasonmolenda updated https://github.com/llvm/llvm-project/pull/115963 >From f8f1d70d1d9eac6d36c0fa84e2a94c032385da39 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Tue, 12 Nov 2024 15:55:15 -0800 Subject: [PATCH 1/6] [lldb] Handle an empty SBMemoryRegionInfo from scripted process A scripted process implementation might return an SBMemoryRegionInfo object in its implementation of `get_memory_region_containing_address` which will have an address 0 and size 0, without realizing the problems this can cause. One problem happens when an expression is run, and lldb needs to find part of the target's virtual address space to store the result (actually stored in lldb's host memory), it uses IRMemoryMap::FindSpace() to do that. If the process supports GetMemoryRegionInfo, FindSpace will step through the allocated memory ranges looking for an unused one. But if every request is a memory region with address 0 + size 0, this loop will never terminate. Detect this kind of response from a scripted process plugin and return an error, so callers iterating over the address space can exit. Added a test where I copied dummy_scripted_process.py from the TestScriptedProcess.py existing test, and added a bad `get_memory_region_containing_address` implementation. rdar://139678032 --- .../Process/scripted/ScriptedProcess.cpp | 9 +- .../Makefile | 3 + .../TestScriptedProcessEmptyMemoryRegion.py | 33 + .../dummy_scripted_process.py | 137 ++ .../main.c| 1 + 5 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile create mode 100644 lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py create mode 100644 lldb/test/API/functionalities/scripted_process_empty_memory_region/dummy_scripted_process.py create mode 100644 lldb/test/API/functionalities/scripted_process_empty_memory_region/main.c diff --git a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp index d2111ce877ce55..c56e24a4ebd188 100644 --- a/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp +++ b/lldb/source/Plugins/Process/scripted/ScriptedProcess.cpp @@ -288,8 +288,15 @@ Status ScriptedProcess::DoGetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion) { Status error; if (auto region_or_err = - GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) + GetInterface().GetMemoryRegionContainingAddress(load_addr, error)) { region = *region_or_err; +if (region.GetRange().GetRangeBase() == 0 && +(region.GetRange().GetByteSize() == 0 || + region.GetRange().GetByteSize() == LLDB_INVALID_ADDRESS)) { + error = Status::FromErrorString( + "Invalid memory region from scripted process"); +} + } return error; } diff --git a/lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile b/lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile new file mode 100644 index 00..10495940055b63 --- /dev/null +++ b/lldb/test/API/functionalities/scripted_process_empty_memory_region/Makefile @@ -0,0 +1,3 @@ +C_SOURCES := main.c + +include Makefile.rules diff --git a/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py b/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py new file mode 100644 index 00..1ff084cfb0278e --- /dev/null +++ b/lldb/test/API/functionalities/scripted_process_empty_memory_region/TestScriptedProcessEmptyMemoryRegion.py @@ -0,0 +1,33 @@ +""" +Test python scripted process which returns an empty SBMemoryRegionInfo +""" + +import os, shutil + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +from lldbsuite.test import lldbtest + + +class ScriptedProcessEmptyMemoryRegion(TestBase): +NO_DEBUG_INFO_TESTCASE = True + +def test_scripted_process_empty_memory_region(self): +"""Test that lldb handles an empty SBMemoryRegionInfo object from +a scripted process plugin.""" +self.build() + +target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) +self.assertTrue(target, VALID_TARGET) + +scripted_process_example_relpath = "dummy_scripted_process.py" +self.runCmd( +"command script import " ++ os.path.join(self.getSourceDir(), scripted_process_example_relpath) +) + +self.expect("memory region 0", error=True, substrs=["Invalid memory region"]) + +self.expect("expr -- 5", substrs=["5"]) diff --git a/lldb/test/API/f
[Lldb-commits] [lldb] 10b048c - [lldb] Make CompilerDecl::GetName (always) return template args (#116068)
Author: Pavel Labath Date: 2024-11-15T12:24:12+01:00 New Revision: 10b048c8922d746b14e991f468e00b3ca67c9d95 URL: https://github.com/llvm/llvm-project/commit/10b048c8922d746b14e991f468e00b3ca67c9d95 DIFF: https://github.com/llvm/llvm-project/commit/10b048c8922d746b14e991f468e00b3ca67c9d95.diff LOG: [lldb] Make CompilerDecl::GetName (always) return template args (#116068) I ran into this while look at a different bug (patch coming soon). This function has only two callers. The first is SBTypeStaticField::GetName (which doesn't care about templates), and the other is CompilerDecl::GetCompilerContext (in the TypeQuery constructor), which does want template arguments. This function was (normally) returning the name without template args. Since this code is only used when looking up a type in another shared library, the odds of running into this bug are relatively low, but I add a test to demonstrate the scenario and the fix for it nonetheless. Amazingly (and scarily), this test actually passes without this change in the default configuration -- and only fails with -gsimple-template-names. The reason for that is that in the non-simplified case we create a regular CXXRecordDecl whose name is "bar" (instead of a template record "foo" with an argument of "int"). When evaluating the expression, we are somehow able to replace this with a proper template specialization decl. Added: lldb/test/API/lang/cpp/forward/Makefile lldb/test/API/lang/cpp/forward/TestCPPForwardDeclaration.py lldb/test/API/lang/cpp/forward/foo.cpp lldb/test/API/lang/cpp/forward/foo.h lldb/test/API/lang/cpp/forward/main.cpp Modified: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp Removed: diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index f5063175d6e070..c5249088a291b8 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9116,7 +9116,7 @@ ConstString TypeSystemClang::DeclGetName(void *opaque_decl) { clang::NamedDecl *nd = llvm::dyn_cast((clang::Decl *)opaque_decl); if (nd != nullptr) - return ConstString(nd->getDeclName().getAsString()); + return ConstString(GetTypeNameForDecl(nd, /*qualified=*/false)); } return ConstString(); } diff --git a/lldb/test/API/lang/cpp/forward/Makefile b/lldb/test/API/lang/cpp/forward/Makefile new file mode 100644 index 00..0b806b314397c5 --- /dev/null +++ b/lldb/test/API/lang/cpp/forward/Makefile @@ -0,0 +1,5 @@ +CXX_SOURCES := main.cpp +DYLIB_CXX_SOURCES := foo.cpp +DYLIB_NAME := foo + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/forward/TestCPPForwardDeclaration.py b/lldb/test/API/lang/cpp/forward/TestCPPForwardDeclaration.py new file mode 100644 index 00..5e9dd9c2227dd5 --- /dev/null +++ b/lldb/test/API/lang/cpp/forward/TestCPPForwardDeclaration.py @@ -0,0 +1,61 @@ +"""Test that forward declaration of a c++ template gets resolved correctly.""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +import lldbsuite.test.lldbutil as lldbutil + + +class ForwardDeclarationTestCase(TestBase): +def do_test(self, dictionary=None): +"""Display *bar_ptr when stopped on a function with forward declaration of struct bar.""" +self.build(dictionary=dictionary) +exe = self.getBuildArtifact("a.out") +target = self.dbg.CreateTarget(exe) +self.assertTrue(target, VALID_TARGET) + +environment = self.registerSharedLibrariesWithTarget(target, ["foo"]) + +# Break inside the foo function which takes a bar_ptr argument. +lldbutil.run_break_set_by_symbol(self, "foo", num_expected_locations=1) + +process = target.LaunchSimple( +None, environment, self.get_process_working_directory() +) +self.assertTrue(process, PROCESS_IS_VALID) + +# The stop reason of the thread should be breakpoint. +self.expect( +"thread list", +STOPPED_DUE_TO_BREAKPOINT, +substrs=["stopped", "stop reason = breakpoint"], +) + +# The breakpoint should have a hit count of 1. +lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1) + +self.expect_expr( +"*bar_ptr", +result_type="bar", +result_children=[ValueCheck(value="47", name="a", type="int")], +) + +def test(self): +self.do_test() + +@no_debug_info_test +@skipIfDarwin +@skipIf(compiler=no_match("clang")) +@skipIf(compiler_version=["<", "8.0"]) +@expectedFailureAll(oslist=["windows"]) +def test_debug_names(self): +"""Test that we are able to find complete types when using DWARF v5 +accelerator tables""" +se
[Lldb-commits] [lldb] [lldb] Make CompilerDecl::GetName (always) return template args (PR #116068)
https://github.com/labath closed https://github.com/llvm/llvm-project/pull/116068 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
labath wrote: > I'm not expert, but everything looks rigorous and you've added a lot of > comments. > > I left a few nits and a singular question. I would encourage comments on some > file descriptors for the less knowledgeable of us (namely me!) That you for the review. Making sure the code is understandable to the uninitiated is an important part of it. https://github.com/llvm/llvm-project/pull/115197 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
https://github.com/labath commented: Do you actually need to parse the headers yourself? The reason for using the llvm implementation was so that we can avoid that. FWICS, all of this data should be available through the `(file|auxiliary)Header(32|64)` APIs. BTW, this is exactly the kind of granularity I was looking for. https://github.com/llvm/llvm-project/pull/116338 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] rm DWARFDebugRanges (PR #116379)
https://github.com/labath created https://github.com/llvm/llvm-project/pull/116379 The class is only used from one place, which is trivial to implement using the llvm class. The main difference is that in the new implementation, the ranges are parsed each time anew (instead of being parsed at startup and cached). I believe this is fine because: - this is already how things work with DWARF v5 debug_rnglists - parsing debug_ranges is fairly fast (definitely faster than rnglists) - generally, this result will be cached at a higher level anyway. Browsing the code I did find one instance where that is not the case -- SymbolFileDWARF::ResolveFunctionAndBlock -- which is called each time we resolve an address (to the block level). However, this function is already pretty suboptimal: it first traverses the DIE tree (which involves parsing all the DIE attributes) to find the correct block, then it parses them again to construct the `lldb_private::Block` representation, and *then* it uses the ID of the block DIE it found in the first step to look up the `Block` object. If this turns out to be a bottleneck, I think there are better ways to optimize it than caching the debug_ranges parse. The motiviation for this is that DWARFDebugRanges sorts the block ranges, even though the order of the ranges is load-bearing (in the absence of DW_AT_low_pc, the "base address" of a scope is determined by the first range entry). Delaying the parsing (and sorting) step makes it easier to access the first entry. >From 64053f9e0549cf5401d2a4e82a1fd3822031346e Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 15 Nov 2024 12:55:17 +0100 Subject: [PATCH] [lldb] rm DWARFDebugRanges The class is only used from one place, which is trivial to implement using the llvm class. The main difference is that in the new implementation, the ranges are parsed each time anew (instead of being parsed at startup and cached). I believe this is fine because: - this is already how things work with DWARF v5 debug_rnglists - parsing debug_ranges is fairly fast (definitely faster than rnglists) - generally, this result will be cached at a higher level anyway. Browsing the code I did find one instance where that is not the case -- SymbolFileDWARF::ResolveFunctionAndBlock -- which is called each time we resolve an address (to the block level). However, this function is already pretty suboptimal: it first traverses the DIE tree (which involves parsing all the DIE attributes) to find the correct block, then it parses them again to construct the `lldb_private::Block` representation, and *then* it uses the ID of the block DIE it found in the first step to look up the `Block` object. If this turns out to be a bottleneck, I think there are better ways to optimize it than caching the debug_ranges parse. The motiviation for this is that DWARFDebugRanges sorts the block ranges, even though the order of the ranges is load-bearing (in the absence of DW_AT_low_pc, the "base address" of a scope is determined by the first range entry). Delaying the parsing (and sorting) step makes it easier to access the first entry. --- .../Plugins/SymbolFile/DWARF/CMakeLists.txt | 1 - .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 1 - .../SymbolFile/DWARF/DWARFDebugInfoEntry.h| 1 - .../SymbolFile/DWARF/DWARFDebugRanges.cpp | 56 -- .../SymbolFile/DWARF/DWARFDebugRanges.h | 34 - .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp| 74 ++- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 14 .../SymbolFile/DWARF/SymbolFileDWARF.h| 4 - .../DWARF/x86/debug_ranges-missing-section.s | 2 +- 9 files changed, 42 insertions(+), 145 deletions(-) delete mode 100644 lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp delete mode 100644 lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index ea644a61b1bdaa..e87194dfe74cb3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -21,7 +21,6 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN DWARFDebugInfo.cpp DWARFDebugInfoEntry.cpp DWARFDebugMacro.cpp - DWARFDebugRanges.cpp DWARFDeclContext.cpp DWARFDefines.cpp DWARFDIE.cpp diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index c0a2066f8239e5..4ecb2ed616a128 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -25,7 +25,6 @@ #include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" -#include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" #include "DWARFFormValue.h" #include "DWARFUnit.h" diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebug
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/115197 >From 2627a1fc1c0722c72793a3f3e4e9520a65897c20 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Tue, 29 Oct 2024 16:56:40 +0100 Subject: [PATCH 1/2] [lldb] Unify/improve MainLoop signal handling Change the signal handler to use a pipe to notify about incoming signals. This has two benefits: - the signal no longer has to happen on the MainLoop thread. With the previous implementation, this had to be the case as that was the only way to ensure that ppoll gets interrupted correctly. In a multithreaded process, this would mean that all other threads have to have the signal blocked at all times. - we don't need the android-specific workaround, which was necessary due to the syscall being implemented in a non-atomic way When the MainLoop class was first implemented, we did not have the interrupt self-pipe, so syscall interruption was the most straight-forward implementation. Over time, the class gained new abilities (the pipe being one of them), so we can now piggy-back on those. This patch also changes the kevent-based implementation to use the pipe for signal notification as well. The motivation there is slightly different: - it makes the implementations more uniform - it makes sure we handle all kinds of signals, like we do with the linux version (EVFILT_SIGNAL only catches process-directed signals) --- lldb/include/lldb/Host/posix/MainLoopPosix.h | 1 + lldb/source/Host/posix/MainLoopPosix.cpp | 182 +++ lldb/unittests/Host/MainLoopTest.cpp | 11 ++ 3 files changed, 75 insertions(+), 119 deletions(-) diff --git a/lldb/include/lldb/Host/posix/MainLoopPosix.h b/lldb/include/lldb/Host/posix/MainLoopPosix.h index 07497b7b8c259a..1988dde7c65aee 100644 --- a/lldb/include/lldb/Host/posix/MainLoopPosix.h +++ b/lldb/include/lldb/Host/posix/MainLoopPosix.h @@ -59,6 +59,7 @@ class MainLoopPosix : public MainLoopBase { private: void ProcessReadObject(IOObject::WaitableHandle handle); void ProcessSignal(int signo); + void ProcessSignals(); class SignalHandle { public: diff --git a/lldb/source/Host/posix/MainLoopPosix.cpp b/lldb/source/Host/posix/MainLoopPosix.cpp index 6f8eaa55cfdf09..34c937f8a05d6c 100644 --- a/lldb/source/Host/posix/MainLoopPosix.cpp +++ b/lldb/source/Host/posix/MainLoopPosix.cpp @@ -17,17 +17,14 @@ #include #include #include +#include #include // Multiplexing is implemented using kqueue on systems that support it (BSD -// variants including OSX). On linux we use ppoll, while android uses pselect -// (ppoll is present but not implemented properly). On windows we use WSApoll -// (which does not support signals). +// variants including OSX). On linux we use ppoll. #if HAVE_SYS_EVENT_H #include -#elif defined(__ANDROID__) -#include #else #include #endif @@ -35,11 +32,38 @@ using namespace lldb; using namespace lldb_private; -static sig_atomic_t g_signal_flags[NSIG]; +namespace { +struct GlobalSignalInfo { + sig_atomic_t pipe_fd = -1; + static_assert(sizeof(sig_atomic_t) >= sizeof(int), +"Type too small for a file descriptor"); + sig_atomic_t flag = 0; +}; +} // namespace +static GlobalSignalInfo g_signal_info[NSIG]; static void SignalHandler(int signo, siginfo_t *info, void *) { assert(signo < NSIG); - g_signal_flags[signo] = 1; + + // Set the flag before writing to the pipe! + g_signal_info[signo].flag = 1; + + char c = '.'; + int fd = g_signal_info[signo].pipe_fd; + if (fd < 0) { +// This can happen with the following (unlikely) sequence of events: +// 1. Thread 1 gets a signal, starts running the signal handler +// 2. Thread 2 unregisters the signal handler, setting pipe_fd to -1 +// 3. Signal handler on thread 1 reads -1 out of pipe_fd +// In this case, we can just ignore the signal because we're no longer +// interested in it. +return; + } + + ssize_t bytes_written = llvm::sys::RetryAfterSignal(-1, ::write, fd, &c, 1); + // We're only using the pipe to wake up the reader, so we can safely ignore + // EAGAIN (pipe full) + assert(bytes_written == 1 || (bytes_written == -1 && errno == EAGAIN)); } class MainLoopPosix::RunImpl { @@ -48,7 +72,7 @@ class MainLoopPosix::RunImpl { ~RunImpl() = default; Status Poll(); - void ProcessEvents(); + void ProcessReadEvents(); private: MainLoopPosix &loop; @@ -58,15 +82,9 @@ class MainLoopPosix::RunImpl { struct kevent out_events[4]; int num_events = -1; -#else -#ifdef __ANDROID__ - fd_set read_fd_set; #else std::vector read_fds; #endif - - sigset_t get_sigmask(); -#endif }; #if HAVE_SYS_EVENT_H @@ -94,7 +112,7 @@ Status MainLoopPosix::RunImpl::Poll() { return Status(); } -void MainLoopPosix::RunImpl::ProcessEvents() { +void MainLoopPosix::RunImpl::ProcessReadEvents() { assert(num_events >= 0); for (int i = 0; i < num_events; ++i) { if (loop.m_terminate_request) @@ -103,9 +
[Lldb-commits] [lldb] [lldb] Handle an empty SBMemoryRegionInfo from scripted process (PR #115963)
https://github.com/labath commented: Thanks Jason. Looks good. (I think the arm failure is due to it being a 32-bit machine. Maybe it would be sufficient to use 32-bit values everywhere?) https://github.com/llvm/llvm-project/pull/115963 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
@@ -179,55 +142,34 @@ Status MainLoopPosix::RunImpl::Poll() { read_fds.push_back(pfd); } - if (ppoll(read_fds.data(), read_fds.size(), nullptr, &sigmask) == -1 && + if (ppoll(read_fds.data(), read_fds.size(), +/*timeout=*/nullptr, +/*sigmask=*/nullptr) == -1 && errno != EINTR) return Status(errno, eErrorTypePOSIX); return Status(); } -#endif -void MainLoopPosix::RunImpl::ProcessEvents() { -#ifdef __ANDROID__ - // Collect first all readable file descriptors into a separate vector and - // then iterate over it to invoke callbacks. Iterating directly over - // loop.m_read_fds is not possible because the callbacks can modify the - // container which could invalidate the iterator. - std::vector fds; - for (const auto &fd : loop.m_read_fds) -if (FD_ISSET(fd.first, &read_fd_set)) - fds.push_back(fd.first); - - for (const auto &handle : fds) { -#else +void MainLoopPosix::RunImpl::ProcessReadEvents() { for (const auto &fd : read_fds) { if ((fd.revents & (POLLIN | POLLHUP)) == 0) continue; IOObject::WaitableHandle handle = fd.fd; -#endif if (loop.m_terminate_request) return; loop.ProcessReadObject(handle); } - - std::vector signals; - for (const auto &entry : loop.m_signals) -if (g_signal_flags[entry.first] != 0) - signals.push_back(entry.first); - - for (const auto &signal : signals) { -if (loop.m_terminate_request) - return; -g_signal_flags[signal] = 0; -loop.ProcessSignal(signal); - } } #endif MainLoopPosix::MainLoopPosix() : m_triggering(false) { Status error = m_trigger_pipe.CreateNew(/*child_process_inherit=*/false); assert(error.Success()); + assert(fcntl(m_trigger_pipe.GetWriteFileDescriptor(), F_SETFL, labath wrote: I'm setting the *flags* on the descriptor. This is essentially `fd->flags |= O_NONBLOCK`. I added a comment and fixed the embarrassing mistake of putting a load-bearing statement into an assert block. https://github.com/llvm/llvm-project/pull/115197 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactor lldb-dap.cpp to not use global DAP variable. (PR #116272)
@@ -5046,30 +5026,48 @@ int main(int argc, char *argv[]) { pause(); } #endif + + // Initialize LLDB first before we do anything. + lldb::SBDebugger::Initialize(); + + // Terminate the debugger before the C++ destructor chain kicks in. + auto terminate_debugger = + llvm::make_scope_exit([] { lldb::SBDebugger::Terminate(); }); + + DAP dap = DAP(program_path.str(), default_repl_mode); labath wrote: Should the dap object be copyable? Given that things hold references to it, maybe the copy operations should be deleted (and this object constructed in place) ? https://github.com/llvm/llvm-project/pull/116272 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][test] Add test categories for Linux and Darwin tests (PR #116194)
https://github.com/dzhidzhoev updated https://github.com/llvm/llvm-project/pull/116194 >From 34047d525f1caeda6817142ec0d53ec8129a6adb Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Thu, 14 Nov 2024 10:21:36 +0100 Subject: [PATCH 1/2] [lldb][test] Add test categories for Linux and Darwin tests Label Linux and Darwin tests with the corresponding categories so that buildbots could be set up to skip them. This is to speed up https://lab.llvm.org/staging/#/builders/195/builds/4739 later. --- lldb/packages/Python/lldbsuite/test/test_categories.py | 3 +++ lldb/test/API/linux/categories | 1 + lldb/test/API/macosx/categories| 1 + 3 files changed, 5 insertions(+) create mode 100644 lldb/test/API/linux/categories create mode 100644 lldb/test/API/macosx/categories diff --git a/lldb/packages/Python/lldbsuite/test/test_categories.py b/lldb/packages/Python/lldbsuite/test/test_categories.py index 036bda9c957d11..537a7aa4025d5c 100644 --- a/lldb/packages/Python/lldbsuite/test/test_categories.py +++ b/lldb/packages/Python/lldbsuite/test/test_categories.py @@ -17,6 +17,7 @@ all_categories = { "basic_process": "Basic process execution sniff tests.", "cmdline": "Tests related to the LLDB command-line interface", +"darwin": "Darwin-related tests", "dataformatters": "Tests related to the type command and the data formatters subsystem", "debugserver": "Debugserver tests", "dsym": "Tests that can be run with DSYM debug information", @@ -30,6 +31,7 @@ "instrumentation-runtime": "Tests for the instrumentation runtime plugins", "libc++": "Test for libc++ data formatters", "libstdcxx": "Test for libstdcxx data formatters", +"linux": "Linux-related tests", "lldb-server": "Tests related to lldb-server", "lldb-dap": "Tests for the Debug Adaptor Protocol with lldb-dap", "llgs": "Tests for the gdb-server functionality of lldb-server", @@ -39,6 +41,7 @@ "std-module": "Tests related to importing the std module", "stresstest": "Tests related to stressing lldb limits", "watchpoint": "Watchpoint-related tests", +"windows": "Windows-related tests", } diff --git a/lldb/test/API/linux/categories b/lldb/test/API/linux/categories new file mode 100644 index 00..a08e1f35eb7c51 --- /dev/null +++ b/lldb/test/API/linux/categories @@ -0,0 +1 @@ +linux diff --git a/lldb/test/API/macosx/categories b/lldb/test/API/macosx/categories new file mode 100644 index 00..1498f270fc2b31 --- /dev/null +++ b/lldb/test/API/macosx/categories @@ -0,0 +1 @@ +darwin >From 561798c1a2eddb43b9d559a08bfcd0d38324bee3 Mon Sep 17 00:00:00 2001 From: Vladislav Dzhidzhoev Date: Fri, 15 Nov 2024 14:24:30 +0100 Subject: [PATCH 2/2] Removed "windows" decorator --- lldb/packages/Python/lldbsuite/test/test_categories.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/packages/Python/lldbsuite/test/test_categories.py b/lldb/packages/Python/lldbsuite/test/test_categories.py index 537a7aa4025d5c..a376f110262dd6 100644 --- a/lldb/packages/Python/lldbsuite/test/test_categories.py +++ b/lldb/packages/Python/lldbsuite/test/test_categories.py @@ -41,7 +41,6 @@ "std-module": "Tests related to importing the std module", "stresstest": "Tests related to stressing lldb limits", "watchpoint": "Watchpoint-related tests", -"windows": "Windows-related tests", } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] e0b76ba - [lldb][test] Disable inline_sites_live.cpp for non-Windows targets (#116196)
Author: Vladislav Dzhidzhoev Date: 2024-11-15T14:15:29+01:00 New Revision: e0b76bafde197c4813aa52dbcfeaf6bd1f9d96da URL: https://github.com/llvm/llvm-project/commit/e0b76bafde197c4813aa52dbcfeaf6bd1f9d96da DIFF: https://github.com/llvm/llvm-project/commit/e0b76bafde197c4813aa52dbcfeaf6bd1f9d96da.diff LOG: [lldb][test] Disable inline_sites_live.cpp for non-Windows targets (#116196) This is a follow-up for the conversation here https://github.com/llvm/llvm-project/pull/115722/. This test is designed for Windows target/PDB format, so it shouldn't be built and run for DWARF/etc. Added: Modified: lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp Removed: diff --git a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp index 549bc881b19bb7..906f3d7dff0a56 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/inline_sites_live.cpp @@ -1,5 +1,5 @@ // clang-format off -// REQUIRES: system-windows +// REQUIRES: target-windows // RUN: %build -o %t.exe -- %s // RUN: %lldb -f %t.exe -s \ ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][test] Add test categories for Linux and Darwin tests (PR #116194)
dzhidzhoev wrote: > Is the real, underlying problem that `skipUnlessDarwin` is checking the host > platform instead of the target platform? I'm somewhat worried about adding a > category that (at first glance) competes with the existing decorators and the > associated risk of folks misunderstanding/misusing them. No, regarding "darwin", it's about these tests from here https://lab.llvm.org/staging/#/builders/197/builds/363/steps/17/logs/stdio ``` PASS: lldb-api :: macosx/load-kext/TestLoadKext.py (995 of 1211) PASS: lldb-api :: macosx/duplicate-archive-members/TestDuplicateMembers.py (996 of 1211) PASS: lldb-api :: macosx/version_zero/TestGetVersionZeroVersion.py (1017 of 1211) ``` There are no decorators in them. > I'm somewhat worried about adding a category that (at first glance) competes > with the existing decorators and the associated risk of folks > misunderstanding/misusing them. I agree with that. Maybe they should be renamed somehow to emphasize that it's for builbot purposes, not for failing/unsupported tests? Like `macosx-oriented`? https://github.com/llvm/llvm-project/pull/116194 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Unify/improve MainLoop signal handling (PR #115197)
@@ -17,29 +17,53 @@ #include #include #include +#include #include // Multiplexing is implemented using kqueue on systems that support it (BSD -// variants including OSX). On linux we use ppoll, while android uses pselect -// (ppoll is present but not implemented properly). On windows we use WSApoll -// (which does not support signals). +// variants including OSX). On linux we use ppoll. #if HAVE_SYS_EVENT_H #include -#elif defined(__ANDROID__) -#include #else #include #endif using namespace lldb; using namespace lldb_private; -static sig_atomic_t g_signal_flags[NSIG]; +namespace { +struct GlobalSignalInfo { + sig_atomic_t pipe_fd = -1; + static_assert(sizeof(sig_atomic_t) >= sizeof(int), +"Type too small for a file descriptor"); + sig_atomic_t flag = 0; +}; +} // namespace +static GlobalSignalInfo g_signal_info[NSIG]; static void SignalHandler(int signo, siginfo_t *info, void *) { assert(signo < NSIG); - g_signal_flags[signo] = 1; + + // Set the flag before writing to the pipe! + g_signal_info[signo].flag = 1; + + char c = '.'; labath wrote: I added a comment about the intent. I think `c` is a good name for an entity with such a short scope. The choice of character is irrelevant -- we only need to write something to force `poll` to return. https://github.com/llvm/llvm-project/pull/115197 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] fix: Target Process may crash or freezes on detaching process on windows (PR #115712)
https://github.com/labath closed https://github.com/llvm/llvm-project/pull/115712 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 5bbe63e - fix: Target Process may crash or freezes on detaching process on windows (#115712)
Author: anatawa12 Date: 2024-11-15T10:52:36+01:00 New Revision: 5bbe63ec91226c0026c6f1ed726c45bb117544e0 URL: https://github.com/llvm/llvm-project/commit/5bbe63ec91226c0026c6f1ed726c45bb117544e0 DIFF: https://github.com/llvm/llvm-project/commit/5bbe63ec91226c0026c6f1ed726c45bb117544e0.diff LOG: fix: Target Process may crash or freezes on detaching process on windows (#115712) Fixes #67825 Fixes #89077 Fixes [RIDER-99436](https://youtrack.jetbrains.com/issue/RIDER-99436/Unity-Editor-will-be-crashed-when-detaching-LLDB-debugger-in-Rider), which is upstream issue of #67825. This PR changes the timing of calling `DebugActiveProcessStop` to after calling `ContinueDebugEvent` for last debugger exception. I confirmed the crashing behavior is because we call `DebugActiveProcessStop` before `ContinueDebugEvent` for last debugger exception with https://github.com/anatawa12/debug-api-test. Added: Modified: lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp lldb/source/Plugins/Process/Windows/Common/DebuggerThread.h lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp lldb/test/API/commands/process/detach-resumes/TestDetachResumes.py Removed: diff --git a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp index ca8e9c078e1f99..b637238007b882 100644 --- a/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/DebuggerThread.cpp @@ -239,12 +239,13 @@ void DebuggerThread::DebugLoop() { BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); if (wait_result) { DWORD continue_status = DBG_CONTINUE; + bool shutting_down = m_is_shutting_down; switch (dbe.dwDebugEventCode) { default: llvm_unreachable("Unhandle debug event code!"); case EXCEPTION_DEBUG_EVENT: { -ExceptionResult status = -HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); +ExceptionResult status = HandleExceptionEvent( +dbe.u.Exception, dbe.dwThreadId, shutting_down); if (status == ExceptionResult::MaskException) continue_status = DBG_CONTINUE; @@ -292,6 +293,45 @@ void DebuggerThread::DebugLoop() { ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); + // We have to DebugActiveProcessStop after ContinueDebugEvent, otherwise + // the target process will crash + if (shutting_down) { +// A breakpoint that occurs while `m_pid_to_detach` is non-zero is a +// magic exception that we use simply to wake up the DebuggerThread so +// that we can close out the debug loop. +if (m_pid_to_detach != 0 && +(dbe.u.Exception.ExceptionRecord.ExceptionCode == + EXCEPTION_BREAKPOINT || + dbe.u.Exception.ExceptionRecord.ExceptionCode == + STATUS_WX86_BREAKPOINT)) { + LLDB_LOG(log, + "Breakpoint exception is cue to detach from process {0:x}", + m_pid_to_detach.load()); + + // detaching with leaving breakpoint exception event on the queue may + // cause target process to crash so process events as possible since + // target threads are running at this time, there is possibility to + // have some breakpoint exception between last WaitForDebugEvent and + // DebugActiveProcessStop but ignore for now. + while (WaitForDebugEvent(&dbe, 0)) { +continue_status = DBG_CONTINUE; +if (dbe.dwDebugEventCode == EXCEPTION_DEBUG_EVENT && +!(dbe.u.Exception.ExceptionRecord.ExceptionCode == + EXCEPTION_BREAKPOINT || + dbe.u.Exception.ExceptionRecord.ExceptionCode == + STATUS_WX86_BREAKPOINT || + dbe.u.Exception.ExceptionRecord.ExceptionCode == + EXCEPTION_SINGLE_STEP)) + continue_status = DBG_EXCEPTION_NOT_HANDLED; +::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, + continue_status); + } + + ::DebugActiveProcessStop(m_pid_to_detach); + m_detached = true; +} + } + if (m_detached) { should_debug = false; } @@ -310,25 +350,18 @@ void DebuggerThread::DebugLoop() { ExceptionResult DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, - DWORD thread_id) { + DWORD thread_id, bool shutting_down) { Log *log = GetLog(WindowsLog::Event | WindowsLog::Exception); - if (m_is_shutting_down) { -// A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic -// exception that -// we use simply to wake up the DebuggerThread so tha
[Lldb-commits] [lldb] fix: Target Process may crash or freezes on detaching process on windows (PR #115712)
github-actions[bot] wrote: @anatawa12 Congratulations on having your first Pull Request (PR) merged into the LLVM Project! Your changes will be combined with recent changes from other authors, then tested by our [build bots](https://lab.llvm.org/buildbot/). If there is a problem with a build, you may receive a report in an email or a comment on this PR. Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues. How to do this, and the rest of the post-merge process, is covered in detail [here](https://llvm.org/docs/MyFirstTypoFix.html#myfirsttypofix-issues-after-landing-your-pr). If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of [LLVM development](https://llvm.org/docs/DeveloperPolicy.html#patch-reversion-policy). You can fix your changes and open a new PR to merge them again. If you don't get any reports, no action is required from you. Your changes are working as expected, well done! https://github.com/llvm/llvm-project/pull/115712 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
labath wrote: > Hi @labath , not sure why the `Labelling new pull requests` check failed. > Also, the build check didnt automatically start for this one. I don't know, but I wouldn't be worried about that. The test failure is more of a concern. https://github.com/llvm/llvm-project/pull/116338 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][test] Disable inline_sites_live.cpp for non-Windows targets (PR #116196)
https://github.com/dzhidzhoev closed https://github.com/llvm/llvm-project/pull/116196 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Add logging for missing `.dwo` files (PR #116436)
https://github.com/vogelsgesang created https://github.com/llvm/llvm-project/pull/116436 I had a hard time to debug a `dwo` file whose file was not found. This log message would have saved me a lot of time. >From 042426896e517cf9e424279c2b25bbf655879a47 Mon Sep 17 00:00:00 2001 From: Adrian Vogelsgesang Date: Fri, 15 Nov 2024 20:13:15 + Subject: [PATCH] [lldb] Add logging for missing `.dwo` files I had a hard time to debug a `dwo` file whose file was not found. This log message would have saved me a lot of time. --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 8 1 file changed, 8 insertions(+) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 666595a6d0635f..2bb41903beb3b4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1963,6 +1963,14 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit( "{1:x16}", error_dwo_path.GetPath().c_str(), cu_die.GetOffset())); +if (Log *log = GetLog(LLDBLog::Symbols)) { + GetObjectFile()->GetModule()->LogMessage( + log, + "unable to locate .dwo debug file \"{0}\" for skeleton DIE " + "{1:x16}", + error_dwo_path.GetPath().c_str(), unit.GetOffset()); +} + if (m_dwo_warning_issued.test_and_set(std::memory_order_relaxed) == false) { GetObjectFile()->GetModule()->ReportWarning( "unable to locate separate debug file (dwo, dwp). Debugging will be " ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
https://github.com/jimingham created https://github.com/llvm/llvm-project/pull/116438 I have some reports of A/B inversion deadlocks between the ThreadPlanStack and the StackFrameList accesses. There's a fair bit of reasonable code in lldb that does "While accessing the ThreadPlanStack, look at that threads's StackFrameList", and also plenty of "While accessing the ThreadPlanStack, look at the StackFrameList." In all the cases I've seen so far, there was at most one of the locks taken that were trying to mutate the list, the other three were just reading. So we could solve the deadlock by converting the two mutexes over to shared mutexes. This patch is the easy part, the ThreadPlanStack mutex. The tricky part was because these were originally recursive mutexes, and recursive access to shared mutexes is undefined behavior according to the C++ standard, I had to add a couple NoLock variants to make sure it didn't get used recursively. Then since the only remaining calls are out to ThreadPlans and ThreadPlans don't have access to their containing ThreadPlanStack, converting this to a non-recursive lock should be safe. >From 943bad7a8faa41d21651de765858dbb49584547c Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Fri, 15 Nov 2024 12:20:33 -0800 Subject: [PATCH] Convert ThreadPlanStack's mutex to a shared mutex. Since shared mutexes are not recursive, I had to add a couple NoLock variants to make sure it didn't get used recursively. --- lldb/include/lldb/Target/ThreadPlanStack.h | 9 ++- lldb/source/Target/ThreadPlanStack.cpp | 81 -- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/lldb/include/lldb/Target/ThreadPlanStack.h b/lldb/include/lldb/Target/ThreadPlanStack.h index e6a560a509261f..cd606bd0bb1056 100644 --- a/lldb/include/lldb/Target/ThreadPlanStack.h +++ b/lldb/include/lldb/Target/ThreadPlanStack.h @@ -14,6 +14,8 @@ #include #include +#include "llvm/Support/RWMutex.h" + #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/lldb-private-forward.h" @@ -96,7 +98,10 @@ class ThreadPlanStack { void ClearThreadCache(); private: - void PrintOneStack(Stream &s, llvm::StringRef stack_name, + + lldb::ThreadPlanSP DiscardPlanNoLock(); + lldb::ThreadPlanSP GetCurrentPlanNoLock() const; + void PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const; @@ -110,7 +115,7 @@ class ThreadPlanStack { size_t m_completed_plan_checkpoint = 0; // Monotonically increasing token for // completed plan checkpoints. std::unordered_map m_completed_plan_store; - mutable std::recursive_mutex m_stack_mutex; + mutable llvm::sys::RWMutex m_stack_mutex; }; class ThreadPlanStackMap { diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp index 1572931429071d..81fcb09b563668 100644 --- a/lldb/source/Target/ThreadPlanStack.cpp +++ b/lldb/source/Target/ThreadPlanStack.cpp @@ -39,21 +39,20 @@ ThreadPlanStack::ThreadPlanStack(const Thread &thread, bool make_null) { void ThreadPlanStack::DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level, bool include_internal) const { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedReader guard(m_stack_mutex); s.IndentMore(); - PrintOneStack(s, "Active plan stack", m_plans, desc_level, include_internal); - PrintOneStack(s, "Completed plan stack", m_completed_plans, desc_level, + PrintOneStackNoLock(s, "Active plan stack", m_plans, desc_level, include_internal); + PrintOneStackNoLock(s, "Completed plan stack", m_completed_plans, desc_level, include_internal); - PrintOneStack(s, "Discarded plan stack", m_discarded_plans, desc_level, + PrintOneStackNoLock(s, "Discarded plan stack", m_discarded_plans, desc_level, include_internal); s.IndentLess(); } -void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, +void ThreadPlanStack::PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const { - std::lock_guard guard(m_stack_mutex); // If the stack is empty, just exit: if (stack.empty()) return; @@ -82,7 +81,7 @@ void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, } size_t ThreadPlanStack::CheckpointCompletedPlans() { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); m_completed_plan_checkpoint++; m_completed_plan_store.insert( std::make_pair(m_completed_plan_checkpoint, m_completed_plans)); @@ -90,7 +89,7 @@ size_t ThreadPlanS
[Lldb-commits] [lldb] [lldb] Convert file address to load address when reading memory for DW_OP_piece (PR #116411)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Ilia Kuklin (kuilpd) Changes When parsing an optimized value and reading a piece from a file address, LLDB tries to read the data from memory using that address. This patch converts file address to load address before reading the memory. Fixes #111313 #97484 --- Full diff: https://github.com/llvm/llvm-project/pull/116411.diff 2 Files Affected: - (modified) lldb/source/Expression/DWARFExpression.cpp (+16-3) - (added) lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c (+23) ``diff diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index f92f25ed342a9c..a7126b25c1cc38 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -1853,12 +1853,25 @@ llvm::Expected DWARFExpression::Evaluate( const Value::ValueType curr_piece_source_value_type = curr_piece_source_value.GetValueType(); Scalar &scalar = curr_piece_source_value.GetScalar(); - const lldb::addr_t addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); + lldb::addr_t addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); switch (curr_piece_source_value_type) { case Value::ValueType::Invalid: return llvm::createStringError("invalid value type"); - case Value::ValueType::LoadAddress: - case Value::ValueType::FileAddress: { + case Value::ValueType::FileAddress: +if (target) { + curr_piece_source_value.ConvertToLoadAddress(module_sp.get(), + target); + addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); +} else { + return llvm::createStringError( + "unable to convert file address 0x%" PRIx64 + " to load address " + "for DW_OP_piece(%" PRIu64 "): " + "no target available", + addr, piece_byte_size); +} +[[fallthrough]]; + case Value::ValueType::LoadAddress: { if (target) { if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) { if (target->ReadMemory(addr, curr_piece.GetBuffer().GetBytes(), diff --git a/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c b/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c new file mode 100644 index 00..d31250426dc112 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c @@ -0,0 +1,23 @@ +// Check that optimized with -O3 values that have a file address can be read +// DWARF info: +// 0x0023: DW_TAG_variable +// DW_AT_name ("array") +// DW_AT_type (0x0032 "char[5]") +// DW_AT_location (DW_OP_piece 0x2, DW_OP_addrx 0x0, DW_OP_piece 0x1) + +// RUN: %clang_host -O3 -gdwarf %s -o %t +// RUN: %lldb %t \ +// RUN: -o "b 22" \ +// RUN: -o "r" \ +// RUN: -o "p/x array[2]" \ +// RUN: -b | FileCheck %s +// +// CHECK: (lldb) p/x array[2] +// CHECK: (char) 0x03 + +static char array[5] = {0, 1, 2, 3, 4}; + +int main(void) { + array[2]++; + return 0; +} \ No newline at end of file `` https://github.com/llvm/llvm-project/pull/116411 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] Convert file address to load address when reading memory for DW_OP_piece (PR #116411)
llvmbot wrote: @llvm/pr-subscribers-debuginfo Author: Ilia Kuklin (kuilpd) Changes When parsing an optimized value and reading a piece from a file address, LLDB tries to read the data from memory using that address. This patch converts file address to load address before reading the memory. Fixes #111313 #97484 --- Full diff: https://github.com/llvm/llvm-project/pull/116411.diff 2 Files Affected: - (modified) lldb/source/Expression/DWARFExpression.cpp (+16-3) - (added) lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c (+23) ``diff diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index f92f25ed342a9c..a7126b25c1cc38 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -1853,12 +1853,25 @@ llvm::Expected DWARFExpression::Evaluate( const Value::ValueType curr_piece_source_value_type = curr_piece_source_value.GetValueType(); Scalar &scalar = curr_piece_source_value.GetScalar(); - const lldb::addr_t addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); + lldb::addr_t addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); switch (curr_piece_source_value_type) { case Value::ValueType::Invalid: return llvm::createStringError("invalid value type"); - case Value::ValueType::LoadAddress: - case Value::ValueType::FileAddress: { + case Value::ValueType::FileAddress: +if (target) { + curr_piece_source_value.ConvertToLoadAddress(module_sp.get(), + target); + addr = scalar.ULongLong(LLDB_INVALID_ADDRESS); +} else { + return llvm::createStringError( + "unable to convert file address 0x%" PRIx64 + " to load address " + "for DW_OP_piece(%" PRIu64 "): " + "no target available", + addr, piece_byte_size); +} +[[fallthrough]]; + case Value::ValueType::LoadAddress: { if (target) { if (curr_piece.ResizeData(piece_byte_size) == piece_byte_size) { if (target->ReadMemory(addr, curr_piece.GetBuffer().GetBytes(), diff --git a/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c b/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c new file mode 100644 index 00..d31250426dc112 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/DW_OP_piece-O3.c @@ -0,0 +1,23 @@ +// Check that optimized with -O3 values that have a file address can be read +// DWARF info: +// 0x0023: DW_TAG_variable +// DW_AT_name ("array") +// DW_AT_type (0x0032 "char[5]") +// DW_AT_location (DW_OP_piece 0x2, DW_OP_addrx 0x0, DW_OP_piece 0x1) + +// RUN: %clang_host -O3 -gdwarf %s -o %t +// RUN: %lldb %t \ +// RUN: -o "b 22" \ +// RUN: -o "r" \ +// RUN: -o "p/x array[2]" \ +// RUN: -b | FileCheck %s +// +// CHECK: (lldb) p/x array[2] +// CHECK: (char) 0x03 + +static char array[5] = {0, 1, 2, 3, 4}; + +int main(void) { + array[2]++; + return 0; +} \ No newline at end of file `` https://github.com/llvm/llvm-project/pull/116411 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -22,8 +22,17 @@ def port: S<"port">, HelpText<"Communicate with the lldb-dap tool over the defined port.">; def: Separate<["-"], "p">, Alias, + MetaVarName<"">, HelpText<"Alias for --port">; +def unix_socket: S<"unix-socket">, + MetaVarName<"">, + HelpText<"Communicate with the lldb-dap tool over the unix socket or named pipe.">; +def: Separate<["-"], "u">, + Alias, + MetaVarName<"">, + HelpText<"Alias for --unix_socket">; vogelsgesang wrote: do we even want to have a short-hand option for sockets? I don't think this will be commonly used manually, so maybe we should not assign a short-hand to it? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] rm DWARFDebugRanges (PR #116379)
https://github.com/JDevlieghere approved this pull request. Beautiful. https://github.com/llvm/llvm-project/pull/116379 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
@@ -250,6 +251,13 @@ def which(program): return None +def pickrandomport(): +"""Returns a random open port.""" +with socket.socket() as sock: +sock.bind(("", 0)) +return sock.getsockname()[1] vogelsgesang wrote: afaict, this will lead to a race condition? The `return` will exit the `with` scope, and we will give up the lock on the port number again? https://github.com/llvm/llvm-project/pull/116392 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [llvm] [DebugInfo] Add explicit visibility macros to CodeView template functions (PR #113102)
vgvassilev wrote: @zmodem, ping. https://github.com/llvm/llvm-project/pull/113102 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
https://github.com/jimingham updated https://github.com/llvm/llvm-project/pull/116438 >From 943bad7a8faa41d21651de765858dbb49584547c Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Fri, 15 Nov 2024 12:20:33 -0800 Subject: [PATCH 1/2] Convert ThreadPlanStack's mutex to a shared mutex. Since shared mutexes are not recursive, I had to add a couple NoLock variants to make sure it didn't get used recursively. --- lldb/include/lldb/Target/ThreadPlanStack.h | 9 ++- lldb/source/Target/ThreadPlanStack.cpp | 81 -- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/lldb/include/lldb/Target/ThreadPlanStack.h b/lldb/include/lldb/Target/ThreadPlanStack.h index e6a560a509261f..cd606bd0bb1056 100644 --- a/lldb/include/lldb/Target/ThreadPlanStack.h +++ b/lldb/include/lldb/Target/ThreadPlanStack.h @@ -14,6 +14,8 @@ #include #include +#include "llvm/Support/RWMutex.h" + #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/lldb-private-forward.h" @@ -96,7 +98,10 @@ class ThreadPlanStack { void ClearThreadCache(); private: - void PrintOneStack(Stream &s, llvm::StringRef stack_name, + + lldb::ThreadPlanSP DiscardPlanNoLock(); + lldb::ThreadPlanSP GetCurrentPlanNoLock() const; + void PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const; @@ -110,7 +115,7 @@ class ThreadPlanStack { size_t m_completed_plan_checkpoint = 0; // Monotonically increasing token for // completed plan checkpoints. std::unordered_map m_completed_plan_store; - mutable std::recursive_mutex m_stack_mutex; + mutable llvm::sys::RWMutex m_stack_mutex; }; class ThreadPlanStackMap { diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp index 1572931429071d..81fcb09b563668 100644 --- a/lldb/source/Target/ThreadPlanStack.cpp +++ b/lldb/source/Target/ThreadPlanStack.cpp @@ -39,21 +39,20 @@ ThreadPlanStack::ThreadPlanStack(const Thread &thread, bool make_null) { void ThreadPlanStack::DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level, bool include_internal) const { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedReader guard(m_stack_mutex); s.IndentMore(); - PrintOneStack(s, "Active plan stack", m_plans, desc_level, include_internal); - PrintOneStack(s, "Completed plan stack", m_completed_plans, desc_level, + PrintOneStackNoLock(s, "Active plan stack", m_plans, desc_level, include_internal); + PrintOneStackNoLock(s, "Completed plan stack", m_completed_plans, desc_level, include_internal); - PrintOneStack(s, "Discarded plan stack", m_discarded_plans, desc_level, + PrintOneStackNoLock(s, "Discarded plan stack", m_discarded_plans, desc_level, include_internal); s.IndentLess(); } -void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, +void ThreadPlanStack::PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const { - std::lock_guard guard(m_stack_mutex); // If the stack is empty, just exit: if (stack.empty()) return; @@ -82,7 +81,7 @@ void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, } size_t ThreadPlanStack::CheckpointCompletedPlans() { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); m_completed_plan_checkpoint++; m_completed_plan_store.insert( std::make_pair(m_completed_plan_checkpoint, m_completed_plans)); @@ -90,7 +89,7 @@ size_t ThreadPlanStack::CheckpointCompletedPlans() { } void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); auto result = m_completed_plan_store.find(checkpoint); assert(result != m_completed_plan_store.end() && "Asked for a checkpoint that didn't exist"); @@ -99,13 +98,13 @@ void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) { } void ThreadPlanStack::DiscardCompletedPlanCheckpoint(size_t checkpoint) { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); m_completed_plan_store.erase(checkpoint); } void ThreadPlanStack::ThreadDestroyed(Thread *thread) { // Tell the plan stacks that this thread is going away: - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); for (ThreadPlanSP plan : m_plans) plan->ThreadDestroyed(); @@ -134,7 +133,7 @@ void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) { // If the threa
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
https://github.com/JDevlieghere commented: Mechanically this change looks good, plus I'm always happy to see another recursive mutex go. One side-effect of this change is that previously, the ThreadPlanStack mutex was indirectly protecting some operations on ThreadPlans too. For example, `ThreadPlan::ClearThreadCache` isn't protected by a mutex, but `ThreadPlanStack::ClearThreadCache` used to be. Assuming the only way multiple threads would interact with this function is through the `ThreadPlanStack`, we now have a potential race because of the reader-lock, while previously this was indirectly protected by the unique lock. I don't know the ThreadPlans enough to determine if that's a problem or not. https://github.com/llvm/llvm-project/pull/116438 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][sbapi][NFC] Remove commented out typedef from SBBreakpointName (PR #116434)
https://github.com/chelcassanova created https://github.com/llvm/llvm-project/pull/116434 SBBreakpointName has a typedef for BreakpointHitCallback used in SetCallback(), but this typedef has been commented out in SBBreakpointName and added instead to SBDefines. Since SB API callbacks are placed in SBDefines, this commit removes this commented out portion. >From 1e1301c3ef833763e168d1462065bee588b759df Mon Sep 17 00:00:00 2001 From: Chelsea Cassanova Date: Fri, 15 Nov 2024 12:00:47 -0800 Subject: [PATCH] [lldb][sbapi] Remove commented out typedef from SBBreakpointName SBBreakpointName has a typedef for BreakpointHitCallback used in SetCallback(), but this typedef has been commented out in SBBreakpointName and added instead to SBDefines. Since SB API callbacks are placed in SBDefines, this commit removes this commented out portion. --- lldb/include/lldb/API/SBBreakpointName.h | 4 1 file changed, 4 deletions(-) diff --git a/lldb/include/lldb/API/SBBreakpointName.h b/lldb/include/lldb/API/SBBreakpointName.h index 838c66385bd121..4b7ad0cce345e5 100644 --- a/lldb/include/lldb/API/SBBreakpointName.h +++ b/lldb/include/lldb/API/SBBreakpointName.h @@ -17,10 +17,6 @@ namespace lldb { class LLDB_API SBBreakpointName { public: -// typedef bool (*BreakpointHitCallback)(void *baton, SBProcess &process, -//SBThread &thread, -//lldb::SBBreakpointLocation &location); - SBBreakpointName(); SBBreakpointName(SBTarget &target, const char *name); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
https://github.com/jimingham updated https://github.com/llvm/llvm-project/pull/116438 >From 943bad7a8faa41d21651de765858dbb49584547c Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Fri, 15 Nov 2024 12:20:33 -0800 Subject: [PATCH 1/3] Convert ThreadPlanStack's mutex to a shared mutex. Since shared mutexes are not recursive, I had to add a couple NoLock variants to make sure it didn't get used recursively. --- lldb/include/lldb/Target/ThreadPlanStack.h | 9 ++- lldb/source/Target/ThreadPlanStack.cpp | 81 -- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/lldb/include/lldb/Target/ThreadPlanStack.h b/lldb/include/lldb/Target/ThreadPlanStack.h index e6a560a509261f..cd606bd0bb1056 100644 --- a/lldb/include/lldb/Target/ThreadPlanStack.h +++ b/lldb/include/lldb/Target/ThreadPlanStack.h @@ -14,6 +14,8 @@ #include #include +#include "llvm/Support/RWMutex.h" + #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/lldb-private-forward.h" @@ -96,7 +98,10 @@ class ThreadPlanStack { void ClearThreadCache(); private: - void PrintOneStack(Stream &s, llvm::StringRef stack_name, + + lldb::ThreadPlanSP DiscardPlanNoLock(); + lldb::ThreadPlanSP GetCurrentPlanNoLock() const; + void PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const; @@ -110,7 +115,7 @@ class ThreadPlanStack { size_t m_completed_plan_checkpoint = 0; // Monotonically increasing token for // completed plan checkpoints. std::unordered_map m_completed_plan_store; - mutable std::recursive_mutex m_stack_mutex; + mutable llvm::sys::RWMutex m_stack_mutex; }; class ThreadPlanStackMap { diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp index 1572931429071d..81fcb09b563668 100644 --- a/lldb/source/Target/ThreadPlanStack.cpp +++ b/lldb/source/Target/ThreadPlanStack.cpp @@ -39,21 +39,20 @@ ThreadPlanStack::ThreadPlanStack(const Thread &thread, bool make_null) { void ThreadPlanStack::DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level, bool include_internal) const { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedReader guard(m_stack_mutex); s.IndentMore(); - PrintOneStack(s, "Active plan stack", m_plans, desc_level, include_internal); - PrintOneStack(s, "Completed plan stack", m_completed_plans, desc_level, + PrintOneStackNoLock(s, "Active plan stack", m_plans, desc_level, include_internal); + PrintOneStackNoLock(s, "Completed plan stack", m_completed_plans, desc_level, include_internal); - PrintOneStack(s, "Discarded plan stack", m_discarded_plans, desc_level, + PrintOneStackNoLock(s, "Discarded plan stack", m_discarded_plans, desc_level, include_internal); s.IndentLess(); } -void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, +void ThreadPlanStack::PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, const PlanStack &stack, lldb::DescriptionLevel desc_level, bool include_internal) const { - std::lock_guard guard(m_stack_mutex); // If the stack is empty, just exit: if (stack.empty()) return; @@ -82,7 +81,7 @@ void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, } size_t ThreadPlanStack::CheckpointCompletedPlans() { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); m_completed_plan_checkpoint++; m_completed_plan_store.insert( std::make_pair(m_completed_plan_checkpoint, m_completed_plans)); @@ -90,7 +89,7 @@ size_t ThreadPlanStack::CheckpointCompletedPlans() { } void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); auto result = m_completed_plan_store.find(checkpoint); assert(result != m_completed_plan_store.end() && "Asked for a checkpoint that didn't exist"); @@ -99,13 +98,13 @@ void ThreadPlanStack::RestoreCompletedPlanCheckpoint(size_t checkpoint) { } void ThreadPlanStack::DiscardCompletedPlanCheckpoint(size_t checkpoint) { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); m_completed_plan_store.erase(checkpoint); } void ThreadPlanStack::ThreadDestroyed(Thread *thread) { // Tell the plan stacks that this thread is going away: - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedWriter guard(m_stack_mutex); for (ThreadPlanSP plan : m_plans) plan->ThreadDestroyed(); @@ -134,7 +133,7 @@ void ThreadPlanStack::PushPlan(lldb::ThreadPlanSP new_plan_sp) { // If the threa
[Lldb-commits] [lldb] Convert ThreadPlanStack's mutex to a shared mutex. (PR #116438)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: None (jimingham) Changes I have some reports of A/B inversion deadlocks between the ThreadPlanStack and the StackFrameList accesses. There's a fair bit of reasonable code in lldb that does "While accessing the ThreadPlanStack, look at that threads's StackFrameList", and also plenty of "While accessing the ThreadPlanStack, look at the StackFrameList." In all the cases I've seen so far, there was at most one of the locks taken that were trying to mutate the list, the other three were just reading. So we could solve the deadlock by converting the two mutexes over to shared mutexes. This patch is the easy part, the ThreadPlanStack mutex. The tricky part was because these were originally recursive mutexes, and recursive access to shared mutexes is undefined behavior according to the C++ standard, I had to add a couple NoLock variants to make sure it didn't get used recursively. Then since the only remaining calls are out to ThreadPlans and ThreadPlans don't have access to their containing ThreadPlanStack, converting this to a non-recursive lock should be safe. --- Full diff: https://github.com/llvm/llvm-project/pull/116438.diff 2 Files Affected: - (modified) lldb/include/lldb/Target/ThreadPlanStack.h (+9-4) - (modified) lldb/source/Target/ThreadPlanStack.cpp (+59-49) ``diff diff --git a/lldb/include/lldb/Target/ThreadPlanStack.h b/lldb/include/lldb/Target/ThreadPlanStack.h index e6a560a509261f..e0f8104de9a4d1 100644 --- a/lldb/include/lldb/Target/ThreadPlanStack.h +++ b/lldb/include/lldb/Target/ThreadPlanStack.h @@ -14,6 +14,8 @@ #include #include +#include "llvm/Support/RWMutex.h" + #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/lldb-private-forward.h" @@ -96,9 +98,12 @@ class ThreadPlanStack { void ClearThreadCache(); private: - void PrintOneStack(Stream &s, llvm::StringRef stack_name, - const PlanStack &stack, lldb::DescriptionLevel desc_level, - bool include_internal) const; + lldb::ThreadPlanSP DiscardPlanNoLock(); + lldb::ThreadPlanSP GetCurrentPlanNoLock() const; + void PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, + const PlanStack &stack, + lldb::DescriptionLevel desc_level, + bool include_internal) const; PlanStack m_plans; ///< The stack of plans this thread is executing. PlanStack m_completed_plans; ///< Plans that have been completed by this @@ -110,7 +115,7 @@ class ThreadPlanStack { size_t m_completed_plan_checkpoint = 0; // Monotonically increasing token for // completed plan checkpoints. std::unordered_map m_completed_plan_store; - mutable std::recursive_mutex m_stack_mutex; + mutable llvm::sys::RWMutex m_stack_mutex; }; class ThreadPlanStackMap { diff --git a/lldb/source/Target/ThreadPlanStack.cpp b/lldb/source/Target/ThreadPlanStack.cpp index 1572931429071d..d5d600dda47a3f 100644 --- a/lldb/source/Target/ThreadPlanStack.cpp +++ b/lldb/source/Target/ThreadPlanStack.cpp @@ -39,21 +39,21 @@ ThreadPlanStack::ThreadPlanStack(const Thread &thread, bool make_null) { void ThreadPlanStack::DumpThreadPlans(Stream &s, lldb::DescriptionLevel desc_level, bool include_internal) const { - std::lock_guard guard(m_stack_mutex); + llvm::sys::ScopedReader guard(m_stack_mutex); s.IndentMore(); - PrintOneStack(s, "Active plan stack", m_plans, desc_level, include_internal); - PrintOneStack(s, "Completed plan stack", m_completed_plans, desc_level, -include_internal); - PrintOneStack(s, "Discarded plan stack", m_discarded_plans, desc_level, -include_internal); + PrintOneStackNoLock(s, "Active plan stack", m_plans, desc_level, + include_internal); + PrintOneStackNoLock(s, "Completed plan stack", m_completed_plans, desc_level, + include_internal); + PrintOneStackNoLock(s, "Discarded plan stack", m_discarded_plans, desc_level, + include_internal); s.IndentLess(); } -void ThreadPlanStack::PrintOneStack(Stream &s, llvm::StringRef stack_name, -const PlanStack &stack, -lldb::DescriptionLevel desc_level, -bool include_internal) const { - std::lock_guard guard(m_stack_mutex); +void ThreadPlanStack::PrintOneStackNoLock(Stream &s, llvm::StringRef stack_name, + const PlanStack &stack, + lldb::DescriptionLevel desc_level, + bool include_internal) const { // If the stack is empty, just exit: if (stack.empty()) return; @@ -82,7 +82,7 @@ void ThreadPlanStack:
[Lldb-commits] [lldb] [lldb][sbapi][NFC] Remove commented out typedef from SBBreakpointName (PR #116434)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Chelsea Cassanova (chelcassanova) Changes SBBreakpointName has a typedef for BreakpointHitCallback used in SetCallback(), but this typedef has been commented out in SBBreakpointName and added instead to SBDefines. Since SB API callbacks are placed in SBDefines, this commit removes this commented out portion. --- Full diff: https://github.com/llvm/llvm-project/pull/116434.diff 1 Files Affected: - (modified) lldb/include/lldb/API/SBBreakpointName.h (-4) ``diff diff --git a/lldb/include/lldb/API/SBBreakpointName.h b/lldb/include/lldb/API/SBBreakpointName.h index 838c66385bd121..4b7ad0cce345e5 100644 --- a/lldb/include/lldb/API/SBBreakpointName.h +++ b/lldb/include/lldb/API/SBBreakpointName.h @@ -17,10 +17,6 @@ namespace lldb { class LLDB_API SBBreakpointName { public: -// typedef bool (*BreakpointHitCallback)(void *baton, SBProcess &process, -//SBThread &thread, -//lldb::SBBreakpointLocation &location); - SBBreakpointName(); SBBreakpointName(SBTarget &target, const char *name); `` https://github.com/llvm/llvm-project/pull/116434 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][AIX] Added XCOFF Object File Header Parsing (PR #116337)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Dhruv Srivastava (DhruvSrivastavaX) Changes This PR is in reference to porting LLDB on AIX. Link to discussions on llvm discourse and github: 1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640 2. https://github.com/llvm/llvm-project/issues/101657 The complete changes for porting are present in this draft PR: https://github.com/llvm/llvm-project/pull/102601 Added XCOFF Object File Header Parsing for AIX. This PR is an incremental PR to the base: - #111814 Details about XCOFF file format on AIX: [XCOFF](https://www.ibm.com/docs/en/aix/7.3?topic=formats-xcoff-object-file-format) Review Request: @labath @DavidSpickett --- Full diff: https://github.com/llvm/llvm-project/pull/116337.diff 2 Files Affected: - (modified) lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp (+123-3) - (modified) lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h (+58) ``diff diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 3be900f9a4bc9f..c06ece4347822d 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_up) return nullptr; + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) +return nullptr; + + if (!objfile_up->ParseHeader()) +return nullptr; + return objfile_up.release(); } +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) +return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), +m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { +LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); +return false; + } + + // Make sure we only handle XCOFF format. + m_binary = + llvm::unique_dyn_cast(std::move(*binary)); + if (!m_binary) +return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { @@ -136,13 +171,92 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, return XCOFFHeaderSizeFromMagic(magic) != 0; } -bool ObjectFileXCOFF::ParseHeader() { return false; } +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { +std::lock_guard guard(module_sp->GetMutex()); +lldb::offset_t offset = 0; + +if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) +ParseXCOFFOptionalHeader(m_data, &offset); +} +return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + // FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( +lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + // FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfData = data.GetU16(o
[Lldb-commits] [lldb] [lldb] Improve editline completion formatting (PR #116456)
JDevlieghere wrote: I've made this a draft because this still needs a test. https://github.com/llvm/llvm-project/pull/116456 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb][sbapi][NFC] Remove commented out typedef from SBBreakpointName (PR #116434)
https://github.com/JDevlieghere approved this pull request. https://github.com/llvm/llvm-project/pull/116434 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb-dap] Refactoring lldb-dap port listening mode to allow multiple connections. (PR #116392)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: John Harrison (ashgti) Changes This refactors the port listening mode to allocate a new DAP object for each connection, allowing multiple connections to run concurrently. --- Patch is 32.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/116392.diff 12 Files Affected: - (modified) lldb/packages/Python/lldbsuite/test/lldbtest.py (+8) - (modified) lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py (+56-19) - (modified) lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py (+27-5) - (added) lldb/test/API/tools/lldb-dap/server/Makefile (+3) - (added) lldb/test/API/tools/lldb-dap/server/TestDAP_server.py (+66) - (added) lldb/test/API/tools/lldb-dap/server/main.c (+6) - (modified) lldb/tools/lldb-dap/DAP.cpp (+5-18) - (modified) lldb/tools/lldb-dap/DAP.h (+27-23) - (modified) lldb/tools/lldb-dap/Options.td (+9) - (modified) lldb/tools/lldb-dap/OutputRedirector.cpp (+4-3) - (modified) lldb/tools/lldb-dap/OutputRedirector.h (+9-3) - (modified) lldb/tools/lldb-dap/lldb-dap.cpp (+286-80) ``diff diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 8884ef5933ada8..a899854bb5ae14 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -39,6 +39,7 @@ import signal from subprocess import * import sys +import socket import time import traceback @@ -250,6 +251,13 @@ def which(program): return None +def pickrandomport(): +"""Returns a random open port.""" +with socket.socket() as sock: +sock.bind(("", 0)) +return sock.getsockname()[1] + + class ValueCheck: def __init__( self, diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py index c29992ce9c7848..e4a53fe0d45907 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py @@ -903,7 +903,7 @@ def request_setBreakpoints(self, file_path, line_array, data=None): "sourceModified": False, } if line_array is not None: -args_dict["lines"] = "%s" % line_array +args_dict["lines"] = line_array breakpoints = [] for i, line in enumerate(line_array): breakpoint_data = None @@ -1154,34 +1154,38 @@ class DebugAdaptorServer(DebugCommunication): def __init__( self, executable=None, +launch=True, port=None, +unix_socket=None, init_commands=[], log_file=None, env=None, ): self.process = None -if executable is not None: -adaptor_env = os.environ.copy() -if env is not None: -adaptor_env.update(env) - -if log_file: -adaptor_env["LLDBDAP_LOG"] = log_file -self.process = subprocess.Popen( -[executable], -stdin=subprocess.PIPE, -stdout=subprocess.PIPE, -stderr=subprocess.PIPE, -env=adaptor_env, +if launch: +self.process = DebugAdaptorServer.launch( +executable, +port=port, +unix_socket=unix_socket, +log_file=log_file, +env=env, ) -DebugCommunication.__init__( -self, self.process.stdout, self.process.stdin, init_commands, log_file -) -elif port is not None: + +if port: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("127.0.0.1", port)) DebugCommunication.__init__( -self, s.makefile("r"), s.makefile("w"), init_commands +self, s.makefile("rb"), s.makefile("wb"), init_commands, log_file +) +elif unix_socket: +s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +s.connect(unix_socket) +DebugCommunication.__init__( +self, s.makefile("rb"), s.makefile("wb"), init_commands, log_file +) +else: +DebugCommunication.__init__( +self, self.process.stdout, self.process.stdin, init_commands, log_file ) def get_pid(self): @@ -1196,6 +1200,39 @@ def terminate(self): self.process.wait() self.process = None +@classmethod +def launch( +cls, executable: str, /, port=None, unix_socket=None, log_file=None, env=None +) -> subprocess.Popen: +adaptor_env = os.environ.copy() +if env: +adaptor_env.update(env) + +if log_file: +adaptor_env["LLDBDAP_LOG"] = log_file + +
[Lldb-commits] [lldb] [lldb] rm DWARFDebugRanges (PR #116379)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Pavel Labath (labath) Changes The class is only used from one place, which is trivial to implement using the llvm class. The main difference is that in the new implementation, the ranges are parsed each time anew (instead of being parsed at startup and cached). I believe this is fine because: - this is already how things work with DWARF v5 debug_rnglists - parsing debug_ranges is fairly fast (definitely faster than rnglists) - generally, this result will be cached at a higher level anyway. Browsing the code I did find one instance where that is not the case -- SymbolFileDWARF::ResolveFunctionAndBlock -- which is called each time we resolve an address (to the block level). However, this function is already pretty suboptimal: it first traverses the DIE tree (which involves parsing all the DIE attributes) to find the correct block, then it parses them again to construct the `lldb_private::Block` representation, and *then* it uses the ID of the block DIE it found in the first step to look up the `Block` object. If this turns out to be a bottleneck, I think there are better ways to optimize it than caching the debug_ranges parse. The motiviation for this is that DWARFDebugRanges sorts the block ranges, even though the order of the ranges is load-bearing (in the absence of DW_AT_low_pc, the "base address" of a scope is determined by the first range entry). Delaying the parsing (and sorting) step makes it easier to access the first entry. --- Full diff: https://github.com/llvm/llvm-project/pull/116379.diff 9 Files Affected: - (modified) lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt (-1) - (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp (-1) - (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h (-1) - (removed) lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp (-56) - (removed) lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h (-34) - (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp (+41-33) - (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (-14) - (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (-4) - (modified) lldb/test/Shell/SymbolFile/DWARF/x86/debug_ranges-missing-section.s (+1-1) ``diff diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index ea644a61b1bdaa..e87194dfe74cb3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -21,7 +21,6 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN DWARFDebugInfo.cpp DWARFDebugInfoEntry.cpp DWARFDebugMacro.cpp - DWARFDebugRanges.cpp DWARFDeclContext.cpp DWARFDefines.cpp DWARFDIE.cpp diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index c0a2066f8239e5..4ecb2ed616a128 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -25,7 +25,6 @@ #include "DWARFCompileUnit.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" -#include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" #include "DWARFFormValue.h" #include "DWARFUnit.h" diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 20c07c95ec47b5..0e50aab3292ae6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -14,7 +14,6 @@ #include "DWARFAttribute.h" #include "DWARFBaseDIE.h" -#include "DWARFDebugRanges.h" #include #include #include diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp deleted file mode 100644 index fd8f4e12ff770c..00 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp +++ /dev/null @@ -1,56 +0,0 @@ -//===-- DWARFDebugRanges.cpp --===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===--===// - -#include "DWARFDebugRanges.h" -#include "DWARFUnit.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" - -using namespace lldb_private; -using namespace lldb_private::plugin::dwarf; - -DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {} - -void DWARFDebugRanges::Extract(DWARFContext &context) { - llvm::DWARFDataExtractor extractor = - context.getOrLoadRangesData().GetAsLLVMDWARF(); - llvm::DWARFDebugRangeList extracted_list; - uint64_t current_offset = 0; - auto extract_next_li
[Lldb-commits] [lldb] [lldb][AIX] Header Parsing for XCOFF Object File in AIX (PR #116338)
llvmbot wrote: @llvm/pr-subscribers-lldb Author: Dhruv Srivastava (DhruvSrivastavaX) Changes This PR is in reference to porting LLDB on AIX. Link to discussions on llvm discourse and github: 1. https://discourse.llvm.org/t/port-lldb-to-ibm-aix/80640 2. https://github.com/llvm/llvm-project/issues/101657 The complete changes for porting are present in this draft PR: https://github.com/llvm/llvm-project/pull/102601 Added XCOFF Object File Header Parsing for AIX. This PR is an incremental PR to the base: - https://github.com/llvm/llvm-project/pull/111814 Details about XCOFF file format on AIX: [XCOFF](https://www.ibm.com/docs/en/aix/7.3?topic=formats-xcoff-object-file-format) Review Request: @labath @DavidSpickett --- Full diff: https://github.com/llvm/llvm-project/pull/116338.diff 2 Files Affected: - (modified) lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp (+125-3) - (modified) lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.h (+58) ``diff diff --git a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp index 3be900f9a4bc9f..255171997db399 100644 --- a/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/XCOFF/ObjectFileXCOFF.cpp @@ -81,9 +81,44 @@ ObjectFile *ObjectFileXCOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_up) return nullptr; + // Cache xcoff binary. + if (!objfile_up->CreateBinary()) +return nullptr; + + if (!objfile_up->ParseHeader()) +return nullptr; + return objfile_up.release(); } +bool ObjectFileXCOFF::CreateBinary() { + if (m_binary) +return true; + + Log *log = GetLog(LLDBLog::Object); + + auto binary = llvm::object::XCOFFObjectFile::createObjectFile( + llvm::MemoryBufferRef(toStringRef(m_data.GetData()), +m_file.GetFilename().GetStringRef()), + file_magic::xcoff_object_64); + if (!binary) { +LLDB_LOG_ERROR(log, binary.takeError(), + "Failed to create binary for file ({1}): {0}", m_file); +return false; + } + + // Make sure we only handle XCOFF format. + m_binary = + llvm::unique_dyn_cast(std::move(*binary)); + if (!m_binary) +return false; + + LLDB_LOG(log, "this = {0}, module = {1} ({2}), file = {3}, binary = {4}", + this, GetModule().get(), GetModule()->GetSpecificationDescription(), + m_file.GetPath(), m_binary.get()); + return true; +} + ObjectFile *ObjectFileXCOFF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { @@ -136,13 +171,94 @@ bool ObjectFileXCOFF::MagicBytesMatch(DataBufferSP &data_sp, return XCOFFHeaderSizeFromMagic(magic) != 0; } -bool ObjectFileXCOFF::ParseHeader() { return false; } +bool ObjectFileXCOFF::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (module_sp) { +std::lock_guard guard(module_sp->GetMutex()); +lldb::offset_t offset = 0; + +if (ParseXCOFFHeader(m_data, &offset, m_xcoff_header)) { + m_data.SetAddressByteSize(GetAddressByteSize()); + if (m_xcoff_header.auxhdrsize > 0) +ParseXCOFFOptionalHeader(m_data, &offset); +} +return true; + } + + return false; +} + +bool ObjectFileXCOFF::ParseXCOFFHeader(lldb_private::DataExtractor &data, + lldb::offset_t *offset_ptr, + xcoff_header_t &xcoff_header) { + + // FIXME: data.ValidOffsetForDataOfSize + xcoff_header.magic = data.GetU16(offset_ptr); + xcoff_header.nsects = data.GetU16(offset_ptr); + xcoff_header.modtime = data.GetU32(offset_ptr); + xcoff_header.symoff = data.GetU64(offset_ptr); + xcoff_header.auxhdrsize = data.GetU16(offset_ptr); + xcoff_header.flags = data.GetU16(offset_ptr); + xcoff_header.nsyms = data.GetU32(offset_ptr); + return true; +} + +bool ObjectFileXCOFF::ParseXCOFFOptionalHeader( +lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr) { + lldb::offset_t init_offset = *offset_ptr; + + // FIXME: data.ValidOffsetForDataOfSize + m_xcoff_aux_header.AuxMagic = data.GetU16(offset_ptr); + m_xcoff_aux_header.Version = data.GetU16(offset_ptr); + m_xcoff_aux_header.ReservedForDebugger = data.GetU32(offset_ptr); + m_xcoff_aux_header.TextStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.DataStartAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.TOCAnchorAddr = data.GetU64(offset_ptr); + m_xcoff_aux_header.SecNumOfEntryPoint = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfText = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfData = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfTOC = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfLoader = data.GetU16(offset_ptr); + m_xcoff_aux_header.SecNumOfBSS = data.GetU16(offset_ptr); + m_xcoff_aux_header.MaxAlignOfText = data.GetU16(offset_ptr); + m_xcoff_