friss created this revision. friss added reviewers: jasonmolenda, kubamracek. Herald added subscribers: danielkiss, kristof.beyls. Herald added a project: LLDB.
The memory history plugin for Asan creates a HistoryThread with the recorded PC values provided by the Asan runtime. In other cases, thoses PCs are gathered by LLDB directly. The PCs returned by the Asan runtime are the PCs of the calls in the backtrace, not the return addresses you would normally get when unwinding the stack (look for a call to GetPreviousIntructionPc in AsanGetStack). When the above addresses are passed to the unwinder, it will subtract 1 from each address of the non zero frames because it treats them as return addresses. This can lead to the final report referencing the wrong line. This patch fixes this issue by threading a flag through HistoryThread and HistoryUnwinder that tells them to treat every frame like the first one. The Asan MemoryHistory plugin can then use this flag. This fixes running TestMemoryHistory on arm64 devices, although it's hard to guarantee that the test will continue to exhibit the boundary condition that triggers this bug. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D76341 Files: lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp lldb/source/Plugins/Process/Utility/HistoryThread.cpp lldb/source/Plugins/Process/Utility/HistoryThread.h lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp lldb/source/Plugins/Process/Utility/HistoryUnwind.h
Index: lldb/source/Plugins/Process/Utility/HistoryUnwind.h =================================================================== --- lldb/source/Plugins/Process/Utility/HistoryUnwind.h +++ lldb/source/Plugins/Process/Utility/HistoryUnwind.h @@ -18,7 +18,8 @@ class HistoryUnwind : public lldb_private::Unwind { public: - HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs); + HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses = false); ~HistoryUnwind() override; @@ -35,6 +36,9 @@ private: std::vector<lldb::addr_t> m_pcs; + /// This boolean indicates that the PCs in the non-0 frames are call + /// addresses and not return addresses. + bool m_pcs_are_call_addresses; }; } // namespace lldb_private Index: lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ lldb/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -23,8 +23,10 @@ // Constructor -HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs) - : Unwind(thread), m_pcs(pcs) {} +HistoryUnwind::HistoryUnwind(Thread &thread, std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses) + : Unwind(thread), m_pcs(pcs), + m_pcs_are_call_addresses(pcs_are_call_addresses) {} // Destructor @@ -59,7 +61,10 @@ if (frame_idx < m_pcs.size()) { cfa = frame_idx; pc = m_pcs[frame_idx]; - behaves_like_zeroth_frame = (frame_idx == 0); + if (m_pcs_are_call_addresses) + behaves_like_zeroth_frame = true; + else + behaves_like_zeroth_frame = (frame_idx == 0); return true; } return false; Index: lldb/source/Plugins/Process/Utility/HistoryThread.h =================================================================== --- lldb/source/Plugins/Process/Utility/HistoryThread.h +++ lldb/source/Plugins/Process/Utility/HistoryThread.h @@ -33,7 +33,8 @@ class HistoryThread : public lldb_private::Thread { public: HistoryThread(lldb_private::Process &process, lldb::tid_t tid, - std::vector<lldb::addr_t> pcs); + std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses = false); ~HistoryThread() override; Index: lldb/source/Plugins/Process/Utility/HistoryThread.cpp =================================================================== --- lldb/source/Plugins/Process/Utility/HistoryThread.cpp +++ lldb/source/Plugins/Process/Utility/HistoryThread.cpp @@ -25,12 +25,13 @@ // Constructor HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid, - std::vector<lldb::addr_t> pcs) + std::vector<lldb::addr_t> pcs, + bool pcs_are_call_addresses) : Thread(process, tid, true), m_framelist_mutex(), m_framelist(), m_pcs(pcs), m_extended_unwind_token(LLDB_INVALID_ADDRESS), m_queue_name(), m_thread_name(), m_originating_unique_thread_id(tid), m_queue_id(LLDB_INVALID_QUEUE_ID) { - m_unwinder_up.reset(new HistoryUnwind(*this, pcs)); + m_unwinder_up.reset(new HistoryUnwind(*this, pcs, pcs_are_call_addresses)); Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); LLDB_LOGF(log, "%p HistoryThread::HistoryThread", static_cast<void *>(this)); } Index: lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp =================================================================== --- lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp +++ lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -138,7 +138,12 @@ pcs.push_back(pc); } - HistoryThread *history_thread = new HistoryThread(*process_sp, tid, pcs); + // The ASAN runtime already massages the return addresses into call + // addresses, we don't want LLDB's unwinder to try to locate the previous + // instruction again as this might lead to us reporting a different line. + bool pcs_are_call_addresses = true; + HistoryThread *history_thread = + new HistoryThread(*process_sp, tid, pcs, pcs_are_call_addresses); ThreadSP new_thread_sp(history_thread); std::ostringstream thread_name_with_number; thread_name_with_number << thread_name << " Thread " << tid;
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits