[Lldb-commits] [PATCH] D29669: Hardware breakpoints implementation for AArch64 targets
omjavaid updated this revision to Diff 88505. omjavaid added a comment. This patch has following updates: 1. Support for Arm hardware breakpoints 2. LLDBServer Test cases for testing Z1 z1 packets. 3. Test case to test hardware breakpoint command and multi-threaded hardware breakpoints. 4. Get rid of HardwareBreakpointList class and replaced it with simple map and struct. 5. Fix LLDB Log mismtach to POSIX_LOG 6. Fix arm hardware breakpoint register read/write function. Kindly provide your feedback. Is this all good to go in now? https://reviews.llvm.org/D29669 Files: include/lldb/Host/common/NativeBreakpointList.h include/lldb/Host/common/NativeProcessProtocol.h include/lldb/Host/common/NativeRegisterContext.h include/lldb/Host/common/NativeThreadProtocol.h packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/Makefile packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/TestHWBreakMultiThread.py packages/Python/lldbsuite/test/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp packages/Python/lldbsuite/test/tools/lldb-server/TestLldbGdbServer.py packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py source/Host/common/NativeProcessProtocol.cpp source/Host/common/NativeRegisterContext.cpp source/Plugins/Process/Linux/NativeProcessLinux.cpp source/Plugins/Process/Linux/NativeProcessLinux.h source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h source/Plugins/Process/Linux/NativeThreadLinux.cpp source/Plugins/Process/Linux/NativeThreadLinux.h source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp === --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -2531,12 +2531,14 @@ packet, "Too short z packet, missing software/hardware specifier"); bool want_breakpoint = true; + bool want_hardware = false; const GDBStoppointType stoppoint_type = GDBStoppointType(packet.GetS32(eStoppointInvalid)); switch (stoppoint_type) { case eBreakpointHardware: want_breakpoint = true; +want_hardware = true; break; case eBreakpointSoftware: want_breakpoint = true; @@ -2579,7 +2581,8 @@ if (want_breakpoint) { // Try to clear the breakpoint. -const Error error = m_debugged_process_sp->RemoveBreakpoint(addr); +const Error error = +m_debugged_process_sp->RemoveBreakpoint(addr, want_hardware); if (error.Success()) return SendOKResponse(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); @@ -3037,9 +3040,14 @@ if (packet.GetChar() != ':') return SendErrorResponse(67); - uint32_t num = m_debugged_process_sp->GetMaxWatchpoints(); + auto hw_debug_cap = m_debugged_process_sp->GetHardwareDebugSupportInfo(); + StreamGDBRemote response; - response.Printf("num:%d;", num); + if (hw_debug_cap == llvm::None) +response.Printf("num:0;"); + else +response.Printf("num:%d;", hw_debug_cap->second); + return SendPacketNoLock(response.GetString()); } Index: source/Plugins/Process/Linux/NativeThreadLinux.h === --- source/Plugins/Process/Linux/NativeThreadLinux.h +++ source/Plugins/Process/Linux/NativeThreadLinux.h @@ -46,6 +46,10 @@ Error RemoveWatchpoint(lldb::addr_t addr) override; + Error SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + Error RemoveHardwareBreakpoint(lldb::addr_t addr) override; + private: // - // Interface for friend classes @@ -102,6 +106,7 @@ std::string m_stop_description; using WatchpointIndexMap = std::map; WatchpointIndexMap m_watchpoint_index_map; + WatchpointIndexMap m_hw_break_index_map; llvm::Optional m_step_workaround; }; Index: source/Plugins/Process/Linux/NativeThreadLinux.cpp === --- source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -190,6 +190,38 @@ return Error("Clearing hardware watchpoint failed."); } +Error NativeThreadLinux::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) { + if (m_state == eStateLaunching) +return Error(); + + Error error = RemoveHardwareBreakpoint(addr); + if (error.Fail()) +return error; + + NativeRegisterContextSP reg_ctx = GetRegisterContext()
[Lldb-commits] [lldb] r295168 - Bug 30863 - Step doesn't stop with conditional breakpoint on the next line
Author: bulasevich Date: Wed Feb 15 05:42:47 2017 New Revision: 295168 URL: http://llvm.org/viewvc/llvm-project?rev=295168&view=rev Log: Bug 30863 - Step doesn't stop with conditional breakpoint on the next line Differential Revisions: https://reviews.llvm.org/D26497 (committed r290168, temporary reverted r290197) https://reviews.llvm.org/D28945 (fix for Ubuntu tests fail) https://reviews.llvm.org/D29909 (fix for TestCallThatThrows test fail) Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/Makefile lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/main.cpp Modified: lldb/trunk/include/lldb/Target/Thread.h lldb/trunk/include/lldb/Target/ThreadPlan.h lldb/trunk/source/Target/Process.cpp lldb/trunk/source/Target/StopInfo.cpp lldb/trunk/source/Target/Thread.cpp lldb/trunk/source/Target/ThreadPlanStepInstruction.cpp lldb/trunk/source/Target/ThreadPlanStepRange.cpp Modified: lldb/trunk/include/lldb/Target/Thread.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=295168&r1=295167&r2=295168&view=diff == --- lldb/trunk/include/lldb/Target/Thread.h (original) +++ lldb/trunk/include/lldb/Target/Thread.h Wed Feb 15 05:42:47 2017 @@ -126,6 +126,7 @@ public: // bit of data. lldb::StopInfoSP stop_info_sp; // You have to restore the stop info or you // might continue with the wrong signals. +std::vector m_completed_plan_stack; lldb::RegisterCheckpointSP register_backup_sp; // You need to restore the registers, of course... uint32_t current_inlined_depth; @@ -1029,6 +1030,15 @@ public: bool WasThreadPlanDiscarded(ThreadPlan *plan); //-- + /// Check if we have completed plan to override breakpoint stop reason + /// + /// @return + /// Returns true if completed plan stack is not empty + /// false otherwise. + //-- + bool CompletedPlanOverridesBreakpoint(); + + //-- /// Queues a generic thread plan. /// /// @param[in] plan_sp @@ -1213,6 +1223,8 @@ public: void SetStopInfo(const lldb::StopInfoSP &stop_info_sp); + void ResetStopInfo(); + void SetShouldReportStop(Vote vote); //-- Modified: lldb/trunk/include/lldb/Target/ThreadPlan.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlan.h?rev=295168&r1=295167&r2=295168&view=diff == --- lldb/trunk/include/lldb/Target/ThreadPlan.h (original) +++ lldb/trunk/include/lldb/Target/ThreadPlan.h Wed Feb 15 05:42:47 2017 @@ -40,9 +40,10 @@ namespace lldb_private { // The thread maintaining a thread plan stack, and you program the actions of a // particular thread // by pushing plans onto the plan stack. -// There is always a "Current" plan, which is the head of the plan stack, +// There is always a "Current" plan, which is the top of the plan stack, // though in some cases -// a plan may defer to plans higher in the stack for some piece of information. +// a plan may defer to plans higher in the stack for some piece of information +// (let us define that the plan stack grows downwards). // // The plan stack is never empty, there is always a Base Plan which persists // through the life @@ -109,6 +110,15 @@ namespace lldb_private { // plans in the time between when // your plan gets unshipped and the next resume. // +// Thread State Checkpoint: +// +// Note that calling functions on target process (ThreadPlanCallFunction) changes +// current thread state. The function can be called either by direct user demand or +// internally, for example lldb allocates memory on device to calculate breakpoint +// condition expression - on Linux it is performed by calling mmap on device. +// ThreadStateCheckpoint saves Thread state (stop info and completed +// plan stack) to restore it after completing function call. +// // Over the lifetime of the plan, various methods of the ThreadPlan are then // called in response to changes of state in // the process we are debugging as follows: @@ -149,7 +159,7 @@ namespace lldb_private { // If the Current plan answers "true" then it is asked if the stop should // percolate all the way to the // user by calling the ShouldStop method. If the curr
[Lldb-commits] [PATCH] D29932: Fix TestNameLookup for GCC
This revision was automatically updated to reflect the committed changes. Closed by commit rL295170: Fix TestNameLookup for GCC (authored by labath). Changed prior to commit: https://reviews.llvm.org/D29932?vs=88347&id=88509#toc Repository: rL LLVM https://reviews.llvm.org/D29932 Files: lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py Index: lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py === --- lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py +++ lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py @@ -20,7 +20,6 @@ mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) -@expectedFailureAll(compiler="gcc") def test_target(self): """Exercise SBTarget.FindFunctions() with various name masks. @@ -44,7 +43,7 @@ for i in range(num_symbols): symbol = exe_module.GetSymbolAtIndex(i); name = symbol.GetName() -if name and 'unique_function_name' in name: +if name and 'unique_function_name' in name and '__PRETTY_FUNCTION__' not in name: mangled = symbol.GetMangledName() if mangled: mangled_to_symbol[mangled] = symbol @@ -56,6 +55,7 @@ # Make sure each mangled name turns up exactly one match when looking up # functions by full name and using the mangled name as the name in the # lookup +self.assertGreaterEqual(len(mangled_to_symbol), 6) for mangled in mangled_to_symbol.keys(): symbol_contexts = target.FindFunctions(mangled, lldb.eFunctionNameTypeFull) self.assertTrue(symbol_contexts.GetSize() == 1) Index: lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py === --- lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py +++ lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py @@ -20,7 +20,6 @@ mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) -@expectedFailureAll(compiler="gcc") def test_target(self): """Exercise SBTarget.FindFunctions() with various name masks. @@ -44,7 +43,7 @@ for i in range(num_symbols): symbol = exe_module.GetSymbolAtIndex(i); name = symbol.GetName() -if name and 'unique_function_name' in name: +if name and 'unique_function_name' in name and '__PRETTY_FUNCTION__' not in name: mangled = symbol.GetMangledName() if mangled: mangled_to_symbol[mangled] = symbol @@ -56,6 +55,7 @@ # Make sure each mangled name turns up exactly one match when looking up # functions by full name and using the mangled name as the name in the # lookup +self.assertGreaterEqual(len(mangled_to_symbol), 6) for mangled in mangled_to_symbol.keys(): symbol_contexts = target.FindFunctions(mangled, lldb.eFunctionNameTypeFull) self.assertTrue(symbol_contexts.GetSize() == 1) ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] r295171 - Fix unittests after r295088
Author: labath Date: Wed Feb 15 06:27:19 2017 New Revision: 295171 URL: http://llvm.org/viewvc/llvm-project?rev=295171&view=rev Log: Fix unittests after r295088 This resurrects TestModule.so which got lost during the move and is needed for the ModuleCache test. Added: lldb/trunk/unittests/Target/Inputs/TestModule.so Added: lldb/trunk/unittests/Target/Inputs/TestModule.so URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Target/Inputs/TestModule.so?rev=295171&view=auto == Binary files lldb/trunk/unittests/Target/Inputs/TestModule.so (added) and lldb/trunk/unittests/Target/Inputs/TestModule.so Wed Feb 15 06:27:19 2017 differ ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] r295170 - Fix TestNameLookup for GCC
Author: labath Date: Wed Feb 15 06:27:16 2017 New Revision: 295170 URL: http://llvm.org/viewvc/llvm-project?rev=295170&view=rev Log: Fix TestNameLookup for GCC Summary: GCC emits also symbols for the __PRETTY_FUNCTION__ virtual variable, which we accidentaly pick up when looking for functions for with "unique_function_name" in the name. This makes the target.FindFunctions call fail, as that symbol is not a function. I also strenghten the test a bit to make sure we actually find all the functions we are interested in. I've put a check that we find at least 6 functions, but maybe this should be *exactly* 6 ? Reviewers: clayborg Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D29932 Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py?rev=295170&r1=295169&r2=295170&view=diff == --- lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/python_api/name_lookup/TestNameLookup.py Wed Feb 15 06:27:16 2017 @@ -20,7 +20,6 @@ class TestNameLookup(TestBase): mydir = TestBase.compute_mydir(__file__) @add_test_categories(['pyapi']) -@expectedFailureAll(compiler="gcc") def test_target(self): """Exercise SBTarget.FindFunctions() with various name masks. @@ -44,7 +43,7 @@ class TestNameLookup(TestBase): for i in range(num_symbols): symbol = exe_module.GetSymbolAtIndex(i); name = symbol.GetName() -if name and 'unique_function_name' in name: +if name and 'unique_function_name' in name and '__PRETTY_FUNCTION__' not in name: mangled = symbol.GetMangledName() if mangled: mangled_to_symbol[mangled] = symbol @@ -56,6 +55,7 @@ class TestNameLookup(TestBase): # Make sure each mangled name turns up exactly one match when looking up # functions by full name and using the mangled name as the name in the # lookup +self.assertGreaterEqual(len(mangled_to_symbol), 6) for mangled in mangled_to_symbol.keys(): symbol_contexts = target.FindFunctions(mangled, lldb.eFunctionNameTypeFull) self.assertTrue(symbol_contexts.GetSize() == 1) ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D29985: [lldb] [test] Fix finding LLDB tools when building stand-alone
mgorny created this revision. mgorny added a project: LLDB. Herald added a subscriber: aemerson. Use both LLDB- and LLVM-specific tool/library directories when LLDB is being built stand-alone. This ensures that the freshly-built tools (and libraries) are used correctly. Without this patch, the test suite uses LLVM_TOOLS_DIR and LLVM_LIBS_DIR to locate lldb, and set PATH and LD_LIBRARY_PATH. When doing a stand-alone build, these variables represent the installed LLVM. As a result, tests either fail due to missing lldb executable or use an earlier installed LLDB version rather than the one being built. To solve this, additional LLDB_TOOLS_DIR and LLDB_LIBS_DIR variables are added and populated using LLVM_*_OUTPUT_INTDIR. Those variables contain directories used to output built executables and libraries. In stand-alone builds, they represent the build-tree directories used by LLDB. In integrated builds, they have the same values as LLVM_*_DIR and therefore using them does not harm. The new variables are prepended to PATH and LD_LIBRARY_PATH to ensure that freshly built binaries are preferred over potentially earlier installed ones. Furthermore, the resulting PATH is used to locate tools for substitutions. Repository: rL LLVM https://reviews.llvm.org/D29985 Files: lit/lit.cfg lit/lit.site.cfg.in Index: lit/lit.site.cfg.in === --- lit/lit.site.cfg.in +++ lit/lit.site.cfg.in @@ -6,6 +6,8 @@ config.llvm_libs_dir = "@LLVM_LIBS_DIR@" config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.lldb_obj_root = "@LLDB_BINARY_DIR@" +config.lldb_libs_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@" +config.lldb_tools_dir = "@LLVM_RUNTIME_OUTPUT_INTDIR@" config.target_triple = "@TARGET_TRIPLE@" config.python_executable = "@PYTHON_EXECUTABLE@" config.cc = "@CMAKE_C_COMPILER@" Index: lit/lit.cfg === --- lit/lit.cfg +++ lit/lit.cfg @@ -39,18 +39,24 @@ # Tweak the PATH to include the tools dir and the scripts dir. if lldb_obj_root is not None: +lldb_tools_dir = getattr(config, 'lldb_tools_dir', None) +if not lldb_tools_dir: +lit_config.fatal('No LLDB tools dir set!') llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) if not llvm_tools_dir: lit_config.fatal('No LLVM tools dir set!') -path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH'])) +path = os.path.pathsep.join((lldb_tools_dir, llvm_tools_dir, config.environment['PATH'])) path = os.path.pathsep.join((os.path.join(getattr(config, 'llvm_src_root', None),'test','Scripts'),path)) config.environment['PATH'] = path +lldb_libs_dir = getattr(config, 'lldb_libs_dir', None) +if not lldb_libs_dir: +lit_config.fatal('No LLDB libs dir set!') llvm_libs_dir = getattr(config, 'llvm_libs_dir', None) if not llvm_libs_dir: lit_config.fatal('No LLVM libs dir set!') -path = os.path.pathsep.join((llvm_libs_dir, +path = os.path.pathsep.join((lldb_libs_dir, llvm_libs_dir, config.environment.get('LD_LIBRARY_PATH',''))) config.environment['LD_LIBRARY_PATH'] = path @@ -115,14 +121,14 @@ # Register substitutions config.substitutions.append(('%python', config.python_executable)) -debugserver = lit.util.which('debugserver', llvm_tools_dir) -lldb = lit.util.which('lldb', llvm_tools_dir) +debugserver = lit.util.which('debugserver', config.environment['PATH']) +lldb = lit.util.which('lldb', config.environment['PATH']) if not os.path.exists(config.cc): -config.cc = lit.util.which(config.cc, llvm_tools_dir) +config.cc = lit.util.which(config.cc, config.environment['PATH']) if not os.path.exists(config.cxx): -config.cxx = lit.util.which(config.cxx, llvm_tools_dir) +config.cxx = lit.util.which(config.cxx, config.environment['PATH']) if platform.system() in ['Darwin']: try: @@ -150,11 +156,11 @@ pattern) tool_pipe = tool_match.group(2) tool_name = tool_match.group(4) -tool_path = lit.util.which(tool_name, config.llvm_tools_dir) +tool_path = lit.util.which(tool_name, config.environment['PATH']) if not tool_path: # Warn, but still provide a substitution. lit_config.note( -'Did not find ' + tool_name + ' in ' + config.llvm_tools_dir) +'Did not find ' + tool_name + ' in ' + config.environment['PATH']) config.substitutions.append((pattern, tool_pipe + tool_path)) # Shell execution @@ -192,13 +198,16 @@ # llvm-config knows whether it is compiled with asserts (and) # whether we are operating in release/debug mode. import subprocess +llvm_config = lit.util.which('llvm-config', config.environment['PATH']) +if not llvm_config: +lit_config.fatal("Could not find llvm-config in " + config.environment['PATH']) try: llvm_config_cmd = \ - subprocess.Popen([os.path.join(llvm_too
[Lldb-commits] [PATCH] D29964: Finish breaking the dependency from lldbUtility -> Host
labath added inline comments. Comment at: lldb/source/Utility/VASprintf.cpp:18 + va_list args) { + llvm::SmallString<16> error(""); + It doesn't look like you should need to allocate a stack object with the string every time. Can't you just assign `buf = "..."` in the error case? Comment at: lldb/source/Utility/VASprintf.cpp:28 + if (length < 0) { +buf = error; +goto finish; Could you also have the function return false in case of an error? You can leave the callers ignoring it, as they weren't handling these errors anyway, but now at least they would have a chance. I know this is meant to go away in the future, but noone know how soon will that be, and it seems like a bad idea to introduce a new abstraction with such an obviously flawed interface (as in, the only way to check if it failed is to inspect the printed-to string). https://reviews.llvm.org/D29964 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
Re: [Lldb-commits] [PATCH] D29964: Finish breaking the dependency from lldbUtility -> Host
On Wed, Feb 15, 2017 at 5:54 AM Pavel Labath via Phabricator < revi...@reviews.llvm.org> wrote: > labath added inline comments. > > > > Comment at: lldb/source/Utility/VASprintf.cpp:18 > + va_list args) { > + llvm::SmallString<16> error(""); > + > > It doesn't look like you should need to allocate a stack object with the > string every time. Can't you just assign `buf = "..."` in the error case? > > No because buf is a SmallVectorImpl, which doesn't have a conversion from anything else > > > Comment at: lldb/source/Utility/VASprintf.cpp:28 > + if (length < 0) { > +buf = error; > +goto finish; > > Could you also have the function return false in case of an error? You can > leave the callers ignoring it, as they weren't handling these errors > anyway, but now at least they would have a chance. I know this is meant to > go away in the future, but noone know how soon will that be, and it seems > like a bad idea to introduce a new abstraction with such an obviously > flawed interface (as in, the only way to check if it failed is to inspect > the printed-to string). > > > https://reviews.llvm.org/D29964 > > > > ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] r295189 - Fix debug build of unit tests
Author: labath Date: Wed Feb 15 10:11:51 2017 New Revision: 295189 URL: http://llvm.org/viewvc/llvm-project?rev=295189&view=rev Log: Fix debug build of unit tests Summary: It turns out listing each library twice is not enough to resolve all references in a debug build on linux - a number of executables fails to link with random symbols missing. Increasing the number to three seems to be enough. The choice of lldbCore to set the multiplicity on is somewhat arbitrary, but it seems fitting, as it is the biggest layering transgressor. Reviewers: beanz Subscribers: mgorny, lldb-commits Differential Revision: https://reviews.llvm.org/D29888 Modified: lldb/trunk/source/Core/CMakeLists.txt Modified: lldb/trunk/source/Core/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/CMakeLists.txt?rev=295189&r1=295188&r2=295189&view=diff == --- lldb/trunk/source/Core/CMakeLists.txt (original) +++ lldb/trunk/source/Core/CMakeLists.txt Wed Feb 15 10:11:51 2017 @@ -85,3 +85,6 @@ add_lldb_library(lldbCore Demangle ) +# Needed to properly resolve references in a debug build. +# TODO: Remove once we have better layering +set_target_properties(lldbCore PROPERTIES LINK_INTERFACE_MULTIPLICITY 3) ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D29888: Fix debug build of unit tests
This revision was automatically updated to reflect the committed changes. Closed by commit rL295189: Fix debug build of unit tests (authored by labath). Changed prior to commit: https://reviews.llvm.org/D29888?vs=88177&id=88544#toc Repository: rL LLVM https://reviews.llvm.org/D29888 Files: lldb/trunk/source/Core/CMakeLists.txt Index: lldb/trunk/source/Core/CMakeLists.txt === --- lldb/trunk/source/Core/CMakeLists.txt +++ lldb/trunk/source/Core/CMakeLists.txt @@ -85,3 +85,6 @@ Demangle ) +# Needed to properly resolve references in a debug build. +# TODO: Remove once we have better layering +set_target_properties(lldbCore PROPERTIES LINK_INTERFACE_MULTIPLICITY 3) Index: lldb/trunk/source/Core/CMakeLists.txt === --- lldb/trunk/source/Core/CMakeLists.txt +++ lldb/trunk/source/Core/CMakeLists.txt @@ -85,3 +85,6 @@ Demangle ) +# Needed to properly resolve references in a debug build. +# TODO: Remove once we have better layering +set_target_properties(lldbCore PROPERTIES LINK_INTERFACE_MULTIPLICITY 3) ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] r295190 - Refactor log channel registration mechanism
Author: labath Date: Wed Feb 15 10:11:59 2017 New Revision: 295190 URL: http://llvm.org/viewvc/llvm-project?rev=295190&view=rev Log: Refactor log channel registration mechanism Summary: We currently have two log channel registration mechanisms. One uses a set of function pointers and the other one is based on the PluginManager. The PluginManager dependency is unfortunate, as logging is also used in lldb-server, and the PluginManager pulls in a lot of classes which are not used in lldb-server. Both approach have the problem that they leave too much to do for the user, and so the individual log channels end up reimplementing command line argument parsing, category listing, etc. Here, I replace the PluginManager-based approach with a one. The new API is more declarative, so the user only needs to specify the list of list of channels, their descriptions, etc., and all the common tasks like enabling/disabling categories are hadled by common code. I migrate the LogChannelDWARF (only user of the PluginManager method) to the new API. In the follow-up commits I'll replace the other channels with something similar. Reviewers: clayborg, zturner, beanz Subscribers: aprantl, lldb-commits Differential Revision: https://reviews.llvm.org/D29895 Modified: lldb/trunk/include/lldb/Core/Log.h lldb/trunk/include/lldb/Core/PluginManager.h lldb/trunk/include/lldb/lldb-forward.h lldb/trunk/include/lldb/lldb-private-interfaces.h lldb/trunk/source/Commands/CommandObjectLog.cpp lldb/trunk/source/Core/Log.cpp lldb/trunk/source/Core/PluginManager.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/unittests/Core/LogTest.cpp Modified: lldb/trunk/include/lldb/Core/Log.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Log.h?rev=295190&r1=295189&r2=295190&view=diff == --- lldb/trunk/include/lldb/Core/Log.h (original) +++ lldb/trunk/include/lldb/Core/Log.h Wed Feb 15 10:11:59 2017 @@ -44,6 +44,53 @@ namespace lldb_private { class Log final { public: + // Description of a log channel category. + struct Category { +llvm::StringLiteral name; +llvm::StringLiteral description; +uint32_t flag; + }; + + // This class describes a log channel. It also encapsulates the behavior + // necessary to enable a log channel in an atomic manner. + class Channel { +std::atomic log_ptr; + + public: +const llvm::ArrayRef categories; +const uint32_t default_flags; + +constexpr Channel(llvm::ArrayRef categories, + uint32_t default_flags) +: log_ptr(nullptr), categories(categories), + default_flags(default_flags) {} + +// This function is safe to call at any time +// FIXME: Not true yet, mask access is not atomic +Log *GetLogIfAll(uint32_t mask) { + Log *log = log_ptr.load(std::memory_order_acquire); + if (log && log->GetMask().AllSet(mask)) +return log; + return nullptr; +} + +// This function is safe to call at any time +// FIXME: Not true yet, mask access is not atomic +Log *GetLogIfAny(uint32_t mask) { + Log *log = log_ptr.load(std::memory_order_acquire); + if (log && log->GetMask().AnySet(mask)) +return log; + return nullptr; +} + +// Calls to Enable and disable need to be serialized externally. +void Enable(Log &log, const std::shared_ptr &stream_sp, +uint32_t flags); + +// Calls to Enable and disable need to be serialized externally. +void Disable(uint32_t flags); + }; + //-- // Callback definitions for abstracted plug-in log access. //-- @@ -63,6 +110,9 @@ public: //-- // Static accessors for logging channels //-- + static void Register(llvm::StringRef name, Channel &channel); + static void Unregister(llvm::StringRef name); + static void RegisterLogChannel(const ConstString &channel, const Log::Callbacks &log_callbacks); @@ -73,13 +123,13 @@ public: static bool EnableLogChannel(const std::shared_ptr &log_stream_sp, - uint32_t log_options, const char *channel, + uint32_t log_options, llvm::StringRef channel, const char **categories, Stream &error_stream); - static void - EnableAllLogChannels(const std::shared_ptr &log_stream_sp, - uint32_t log_options, const char **categories, - Stream *feedback_strm); + static bool DisableLogChannel(llvm::StringRef chann
[Lldb-commits] [PATCH] D29895: Refactor log channel registration mechanism
This revision was automatically updated to reflect the committed changes. Closed by commit rL295190: Refactor log channel registration mechanism (authored by labath). Changed prior to commit: https://reviews.llvm.org/D29895?vs=88395&id=88545#toc Repository: rL LLVM https://reviews.llvm.org/D29895 Files: lldb/trunk/include/lldb/Core/Log.h lldb/trunk/include/lldb/Core/PluginManager.h lldb/trunk/include/lldb/lldb-forward.h lldb/trunk/include/lldb/lldb-private-interfaces.h lldb/trunk/source/Commands/CommandObjectLog.cpp lldb/trunk/source/Core/Log.cpp lldb/trunk/source/Core/PluginManager.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/unittests/Core/LogTest.cpp Index: lldb/trunk/unittests/Core/LogTest.cpp === --- lldb/trunk/unittests/Core/LogTest.cpp +++ lldb/trunk/unittests/Core/LogTest.cpp @@ -12,10 +12,30 @@ #include "lldb/Core/Log.h" #include "lldb/Host/Host.h" #include "lldb/Utility/StreamString.h" +#include "llvm/Support/ManagedStatic.h" using namespace lldb; using namespace lldb_private; +enum { FOO = 1, BAR = 2 }; +static constexpr Log::Category test_categories[] = { +{"foo", "log foo", FOO}, {"bar", "log bar", BAR}, +}; +static constexpr uint32_t default_flags = FOO; + +static Log::Channel test_channel(test_categories, default_flags); + +struct LogChannelTest : public ::testing::Test { + static void SetUpTestCase() { +Log::Register("chan", test_channel); + } + + static void TearDownTestCase() { +Log::Unregister("chan"); +llvm::llvm_shutdown(); + } +}; + static std::string GetLogString(uint32_t log_options, const char *format, int arg) { std::string stream_string; @@ -57,3 +77,96 @@ GetLogString(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD, "Hello World {0}", 47)); } + +TEST(LogTest, Register) { + llvm::llvm_shutdown_obj obj; + Log::Register("chan", test_channel); + Log::Unregister("chan"); + Log::Register("chan", test_channel); + Log::Unregister("chan"); +} + +TEST(LogTest, Unregister) { + llvm::llvm_shutdown_obj obj; + Log::Register("chan", test_channel); + EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); + const char *cat1[] = {"foo", nullptr}; + std::string message; + std::shared_ptr stream_sp( + new llvm::raw_string_ostream(message)); + StreamString err; + EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat1, err)); + EXPECT_NE(nullptr, test_channel.GetLogIfAny(FOO)); + Log::Unregister("chan"); + EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO)); +} + +TEST_F(LogChannelTest, Enable) { + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + std::string message; + std::shared_ptr stream_sp( + new llvm::raw_string_ostream(message)); + StreamString err; + EXPECT_FALSE(Log::EnableLogChannel(stream_sp, 0, "chanchan", nullptr, err)); + EXPECT_EQ("Invalid log channel 'chanchan'.\n", err.GetString()); + err.Clear(); + + EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", nullptr, err)); + EXPECT_EQ("", err.GetString()); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + + const char *cat2[] = {"bar", nullptr}; + EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat2, err)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); + + const char *cat3[] = {"baz", nullptr}; + EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat3, err)); + EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'")) + << "err: " << err.GetString().str(); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); +} + +TEST_F(LogChannelTest, Disable) { + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(FOO)); + const char *cat12[] = {"foo", "bar", nullptr}; + std::string message; + std::shared_ptr stream_sp( + new llvm::raw_string_ostream(message)); + StreamString err; + EXPECT_TRUE(Log::EnableLogChannel(stream_sp, 0, "chan", cat12, err)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO | BAR)); + + const char *cat2[] = {"bar", nullptr}; + EXPECT_TRUE(Log::DisableLogChannel("chan", cat2, err)); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + + const char *cat3[] = {"baz", nullptr}; + EXPECT_TRUE(Log::DisableLogChannel("chan", cat3, err)); + EXPECT_TRUE(err.GetString().contains("unrecognized log category 'baz'")) + << "err: " << err.GetString().str(); + EXPECT_NE(nullptr, test_channel.GetLogIfAll(FOO)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAll(BAR)); + err.Clear(); + + EXPECT_TRUE(Log::DisableLogChannel("chan", nullptr, err)); + EXPECT_EQ(nullptr, test_channel.GetLogIfAny(FOO | BAR)); +} + +TEST_F(LogChannelTest, List) { + StreamString str; + EXPECT_
[Lldb-commits] [PATCH] D29144: LLDB: fix for TestCallThatThrows.py test fail
labath added a comment. The test added by this batch is failing on windows http://lab.llvm.org:8011/builders/lldb-windows7-android/builds/2499, for a very prosaic reason - we cannot run a "make clean" as something is holding the executable file open. Based on my debugging, it is not a problem in the test itself, but rather in the liblldb code (e.g. when I change all the breakpoint conditions to true, and adjust expectations accordingly, make clean suceeds). My feeling is something is creating a shared_ptr loop which prevents things from going away when the test is over. I am going to debug this further, but I writing this here, in case you have any ideas where I should start looking. https://reviews.llvm.org/D29144 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] r295201 - Revert "Refactor log channel registration mechanism"
Author: labath Date: Wed Feb 15 11:13:19 2017 New Revision: 295201 URL: http://llvm.org/viewvc/llvm-project?rev=295201&view=rev Log: Revert "Refactor log channel registration mechanism" The change breaks on Windows and NetBSD bots. Revert while I investigate. Modified: lldb/trunk/include/lldb/Core/Log.h lldb/trunk/include/lldb/Core/PluginManager.h lldb/trunk/include/lldb/lldb-forward.h lldb/trunk/include/lldb/lldb-private-interfaces.h lldb/trunk/source/Commands/CommandObjectLog.cpp lldb/trunk/source/Core/Log.cpp lldb/trunk/source/Core/PluginManager.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/unittests/Core/LogTest.cpp Modified: lldb/trunk/include/lldb/Core/Log.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Log.h?rev=295201&r1=295200&r2=295201&view=diff == --- lldb/trunk/include/lldb/Core/Log.h (original) +++ lldb/trunk/include/lldb/Core/Log.h Wed Feb 15 11:13:19 2017 @@ -44,53 +44,6 @@ namespace lldb_private { class Log final { public: - // Description of a log channel category. - struct Category { -llvm::StringLiteral name; -llvm::StringLiteral description; -uint32_t flag; - }; - - // This class describes a log channel. It also encapsulates the behavior - // necessary to enable a log channel in an atomic manner. - class Channel { -std::atomic log_ptr; - - public: -const llvm::ArrayRef categories; -const uint32_t default_flags; - -constexpr Channel(llvm::ArrayRef categories, - uint32_t default_flags) -: log_ptr(nullptr), categories(categories), - default_flags(default_flags) {} - -// This function is safe to call at any time -// FIXME: Not true yet, mask access is not atomic -Log *GetLogIfAll(uint32_t mask) { - Log *log = log_ptr.load(std::memory_order_acquire); - if (log && log->GetMask().AllSet(mask)) -return log; - return nullptr; -} - -// This function is safe to call at any time -// FIXME: Not true yet, mask access is not atomic -Log *GetLogIfAny(uint32_t mask) { - Log *log = log_ptr.load(std::memory_order_acquire); - if (log && log->GetMask().AnySet(mask)) -return log; - return nullptr; -} - -// Calls to Enable and disable need to be serialized externally. -void Enable(Log &log, const std::shared_ptr &stream_sp, -uint32_t flags); - -// Calls to Enable and disable need to be serialized externally. -void Disable(uint32_t flags); - }; - //-- // Callback definitions for abstracted plug-in log access. //-- @@ -110,9 +63,6 @@ public: //-- // Static accessors for logging channels //-- - static void Register(llvm::StringRef name, Channel &channel); - static void Unregister(llvm::StringRef name); - static void RegisterLogChannel(const ConstString &channel, const Log::Callbacks &log_callbacks); @@ -123,13 +73,13 @@ public: static bool EnableLogChannel(const std::shared_ptr &log_stream_sp, - uint32_t log_options, llvm::StringRef channel, + uint32_t log_options, const char *channel, const char **categories, Stream &error_stream); - static bool DisableLogChannel(llvm::StringRef channel, -const char **categories, Stream &error_stream); - - static bool ListChannelCategories(llvm::StringRef channel, Stream &stream); + static void + EnableAllLogChannels(const std::shared_ptr &log_stream_sp, + uint32_t log_options, const char **categories, + Stream *feedback_strm); static void DisableAllLogChannels(Stream *feedback_strm); @@ -140,6 +90,12 @@ public: static void Terminate(); //-- + // Auto completion + //-- + static void AutoCompleteChannelName(const char *channel_name, + StringList &matches); + + //-- // Member functions //-- Log(); @@ -206,6 +162,34 @@ private: const llvm::formatv_object_base &payload); }; +class LogChannel : public PluginInterface { +public: + LogChannel(); + + ~LogChannel() override; + + static lldb::LogChannelSP FindPlugin(
[Lldb-commits] [lldb] r295211 - Skip TestStepOverBreakpoint on windows
Author: labath Date: Wed Feb 15 12:04:50 2017 New Revision: 295211 URL: http://llvm.org/viewvc/llvm-project?rev=295211&view=rev Log: Skip TestStepOverBreakpoint on windows Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py?rev=295211&r1=295210&r2=295211&view=diff == --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py (original) +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/step_over_breakpoint/TestStepOverBreakpoint.py Wed Feb 15 12:04:50 2017 @@ -52,6 +52,7 @@ class StepOverBreakpointsTestCase(TestBa self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(self.process, self.breakpoint1) self.assertIsNotNone(self.thread, "Didn't stop at breakpoint 1.") +@skipIf(bugnumber="llvm.org/pr31972", hostoslist=["windows"]) def test_step_instruction(self): # Count instructions between breakpoint_1 and breakpoint_4 contextList = self.target.FindFunctions('main', lldb.eFunctionNameTypeAuto) @@ -87,6 +88,7 @@ class StepOverBreakpointsTestCase(TestBa self.process.Continue() self.assertEquals(self.process.GetState(), lldb.eStateExited) +@skipIf(bugnumber="llvm.org/pr31972", hostoslist=["windows"]) def test_step_over(self): #lldb.DBG.EnableLog("lldb", ["step","breakpoint"]) ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] r295212 - Fix Xcode project.
Author: gclayton Date: Wed Feb 15 12:24:44 2017 New Revision: 295212 URL: http://llvm.org/viewvc/llvm-project?rev=295212&view=rev Log: Fix Xcode project. Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=295212&r1=295211&r2=295212&view=diff == --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Feb 15 12:24:44 2017 @@ -140,7 +140,6 @@ 2579065F1BD0488D00178368 /* DomainSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065E1BD0488D00178368 /* DomainSocket.cpp */; }; 257906641BD5AFD000178368 /* Acceptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257906621BD5AFD000178368 /* Acceptor.cpp */; }; 257906651BD5AFD000178368 /* Acceptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 257906631BD5AFD000178368 /* Acceptor.h */; }; - 257E47171AA56C2000A62F81 /* ModuleCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257E47151AA56C2000A62F81 /* ModuleCache.cpp */; }; 25EF23781AC09B3700908DF0 /* AdbClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25EF23751AC09AD800908DF0 /* AdbClient.cpp */; }; 260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; 260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; @@ -206,6 +205,8 @@ 265205A813D3E3F700132FE2 /* RegisterContextKDP_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A213D3E3F700132FE2 /* RegisterContextKDP_arm.cpp */; }; 265205AA13D3E3F700132FE2 /* RegisterContextKDP_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A413D3E3F700132FE2 /* RegisterContextKDP_i386.cpp */; }; 265205AC13D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265205A613D3E3F700132FE2 /* RegisterContextKDP_x86_64.cpp */; }; + 2654A6801E54D59400DA1013 /* ModuleCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2654A67F1E54D59400DA1013 /* ModuleCache.cpp */; }; + 2654A6831E54D5E200DA1013 /* RegisterNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2654A6821E54D5E200DA1013 /* RegisterNumber.cpp */; }; 2656BBC31AE0739C00441749 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32A10F3DFDD009D5894 /* libedit.dylib */; }; 2656BBC41AE073A800441749 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; }; 2656BBC51AE073AD00441749 /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; }; @@ -909,7 +910,6 @@ AF1729D7182C907200E0AB97 /* HistoryUnwind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */; }; AF1D88691B575E8D003CB899 /* ValueObjectConstResultCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF94726E1B575E430063D65C /* ValueObjectConstResultCast.cpp */; }; AF1F7B07189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1F7B05189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp */; }; - AF1FA88A1A60A69500272AFC /* RegisterNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1FA8891A60A69500272AFC /* RegisterNumber.cpp */; }; AF20F7661AF18F8500751A6E /* ABISysV_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF20F7641AF18F8500751A6E /* ABISysV_arm.cpp */; }; AF20F76A1AF18F9000751A6E /* ABISysV_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF20F7681AF18F9000751A6E /* ABISysV_arm64.cpp */; }; AF23B4DB19009C66003E2A58 /* FreeBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */; }; @@ -1377,8 +1377,6 @@ 2579065E1BD0488D00178368 /* DomainSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DomainSocket.cpp; sourceTree = ""; }; 257906621BD5AFD000178368 /* Acceptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Acceptor.cpp; path = "tools/lldb-server/Acceptor.cpp"; sourceTree = ""; }; 257906631BD5AFD000178368 /* Acceptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Acceptor.h; path = "tools/lldb-server/Acceptor.h"; sourceTree = ""; }; -
[Lldb-commits] [PATCH] D30006: [lldb] Remove the "MemoryHistory" plugin type and merge it into InstrumentationRuntime
kubamracek created this revision. kubamracek added a project: Sanitizers. Herald added a subscriber: mgorny. There is currently a single MemoryHistory plugin, which is for AddressSanitizer. Let's merge the feature into InstrumentationRuntime plugins. I'm thinking of implementing another provider of memory history, which would be for ThreadSanitizer -- and it would be weird to implement two separate plugins (MemoryHistory and InstrumentationRuntime) to each sanitizer. https://reviews.llvm.org/D30006 Files: include/lldb/Core/PluginManager.h include/lldb/Target/InstrumentationRuntime.h include/lldb/Target/MemoryHistory.h include/lldb/lldb-forward.h include/lldb/lldb-private-interfaces.h lldb.xcodeproj/project.pbxproj source/API/SystemInitializerFull.cpp source/Commands/CommandObjectMemory.cpp source/Core/PluginManager.cpp source/Plugins/CMakeLists.txt source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h source/Plugins/MemoryHistory/CMakeLists.txt source/Plugins/MemoryHistory/asan/CMakeLists.txt source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h source/Target/CMakeLists.txt source/Target/InstrumentationRuntime.cpp source/Target/MemoryHistory.cpp source/Target/Process.cpp Index: source/Target/Process.cpp === --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -47,7 +47,6 @@ #include "lldb/Target/JITLoader.h" #include "lldb/Target/JITLoaderList.h" #include "lldb/Target/LanguageRuntime.h" -#include "lldb/Target/MemoryHistory.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/OperatingSystem.h" @@ -5983,14 +5982,14 @@ ThreadCollectionSP Process::GetHistoryThreads(lldb::addr_t addr) { ThreadCollectionSP threads; - const MemoryHistorySP &memory_history = - MemoryHistory::FindPlugin(shared_from_this()); + const InstrumentationRuntimeSP &runtime = + InstrumentationRuntime::FindMemoryHistoryPlugin(shared_from_this()); - if (!memory_history) { + if (!runtime) { return threads; } - threads.reset(new ThreadCollection(memory_history->GetHistoryThreads(addr))); + threads.reset(new ThreadCollection(runtime->GetHistoryThreads(addr))); return threads; } Index: source/Target/MemoryHistory.cpp === --- source/Target/MemoryHistory.cpp +++ source/Target/MemoryHistory.cpp @@ -1,33 +0,0 @@ -//===-- MemoryHistory.cpp ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--===// - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Target/MemoryHistory.h" -#include "lldb/Core/PluginManager.h" - -using namespace lldb; -using namespace lldb_private; - -lldb::MemoryHistorySP MemoryHistory::FindPlugin(const ProcessSP process) { - MemoryHistoryCreateInstance create_callback = nullptr; - - for (uint32_t idx = 0; - (create_callback = PluginManager::GetMemoryHistoryCreateCallbackAtIndex( -idx)) != nullptr; - ++idx) { -MemoryHistorySP memory_history_sp(create_callback(process)); -if (memory_history_sp) - return memory_history_sp; - } - - return MemoryHistorySP(); -} Index: source/Target/InstrumentationRuntime.cpp === --- source/Target/InstrumentationRuntime.cpp +++ source/Target/InstrumentationRuntime.cpp @@ -78,3 +78,19 @@ StructuredData::ObjectSP info) { return ThreadCollectionSP(new ThreadCollection()); } + +lldb::InstrumentationRuntimeSP +InstrumentationRuntime::FindMemoryHistoryPlugin(const ProcessSP process) { + for (uint32_t idx = 0;; ++idx) { +InstrumentationRuntimeGetType get_type_callback = +PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(idx); +if (get_type_callback == nullptr) + break; +InstrumentationRuntimeType type = get_type_callback(); +InstrumentationRuntimeSP runtime = process->GetInstrumentationRuntime(type); +if (runtime->CanProvideMemoryHistory()) + return runtime; + } + + return InstrumentationRuntimeSP(); +} Index: source/Target/CMakeLists.txt === --- source/Target/CMakeLists.txt +++ source/Target/CMakeLists.txt @@ -12,7 +12,6 @@ Language.cpp LanguageRuntime.cpp Memory.cpp - MemoryHistory.cpp ModuleCache.cpp ObjCLanguageRuntime.cpp OperatingSystem.cpp Index: source/Plugins/MemoryHistory/asan/Memor
[Lldb-commits] [PATCH] D30007: [lldb] Provide API to know which sanitizer generated an eStopReasonInstrumentation
kubamracek created this revision. kubamracek added a project: Sanitizers. We can provide this via StopReason->GetValue(). This is important so that users of SB API can treat various sanitizers differently (the extended stop reason data is also structured differently for different sanitizers). https://reviews.llvm.org/D30007 Files: include/lldb/API/SBThread.h include/lldb/API/SBThreadPlan.h include/lldb/Target/InstrumentationRuntimeStopInfo.h include/lldb/Target/StopInfo.h packages/Python/lldbsuite/test/functionalities/asan/TestMemoryHistory.py packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py packages/Python/lldbsuite/test/functionalities/tsan/basic/TestTsanBasic.py scripts/interface/SBThread.i scripts/interface/SBThreadPlan.i source/API/SBThread.cpp source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp source/Target/InstrumentationRuntimeStopInfo.cpp Index: source/Target/InstrumentationRuntimeStopInfo.cpp === --- source/Target/InstrumentationRuntimeStopInfo.cpp +++ source/Target/InstrumentationRuntimeStopInfo.cpp @@ -17,9 +17,9 @@ using namespace lldb_private; InstrumentationRuntimeStopInfo::InstrumentationRuntimeStopInfo( -Thread &thread, std::string description, +Thread &thread, InstrumentationRuntimeType type, std::string description, StructuredData::ObjectSP additional_data) -: StopInfo(thread, 0) { +: StopInfo(thread, type) { m_extended_info = additional_data; m_description = description; } @@ -30,8 +30,8 @@ StopInfoSP InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData( -Thread &thread, std::string description, +Thread &thread, InstrumentationRuntimeType type, std::string description, StructuredData::ObjectSP additionalData) { return StopInfoSP( - new InstrumentationRuntimeStopInfo(thread, description, additionalData)); + new InstrumentationRuntimeStopInfo(thread, type, description, additionalData)); } Index: source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp === --- source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp +++ source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp @@ -818,7 +818,8 @@ thread_sp->SetStopInfo( InstrumentationRuntimeStopInfo:: CreateStopReasonWithInstrumentationData( - *thread_sp, stop_reason_description, report)); + *thread_sp, eInstrumentationRuntimeTypeThreadSanitizer, + stop_reason_description, report)); StreamFileSP stream_sp( process_sp->GetTarget().GetDebugger().GetOutputFile()); Index: source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp === --- source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp +++ source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp @@ -257,9 +257,11 @@ if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) { ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); if (thread_sp) - thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo:: - CreateStopReasonWithInstrumentationData( - *thread_sp, description, report)); + thread_sp->SetStopInfo( + InstrumentationRuntimeStopInfo:: + CreateStopReasonWithInstrumentationData( + *thread_sp, eInstrumentationRuntimeTypeAddressSanitizer, + description, report)); StreamFileSP stream_sp( process_sp->GetTarget().GetDebugger().GetOutputFile()); Index: source/API/SBThread.cpp === --- source/API/SBThread.cpp +++ source/API/SBThread.cpp @@ -167,7 +167,6 @@ case eStopReasonExec: case eStopReasonPlanComplete: case eStopReasonThreadExiting: -case eStopReasonInstrumentation: // There is no data for these stop reasons. return 0; @@ -190,6 +189,9 @@ case eStopReasonException: return 1; + +case eStopReasonInstrumentation: + return 1; } } } else { @@ -221,7 +223,6 @@ case eStopReasonExec: case eStopReasonPlanComplete: case eStopReasonThreadExiting: -case eStopReasonInstrumentation: // There is no data for these stop reasons. return 0; @@ -255,6 +256,9 @@ case eStopReasonException: return stop_info_sp->GetValue(); + +case eStopReasonInstrumentation: + return stop_info_sp->G
[Lldb-commits] [PATCH] D30007: [lldb] Provide API to know which sanitizer generated an eStopReasonInstrumentation
clayborg added a comment. I am fine as long is Jim Ingham is fine. Jim, if you are good with this, just put it into Accept Revision. https://reviews.llvm.org/D30007 ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D29964: Finish breaking the dependency from lldbUtility -> Host
zturner updated this revision to Diff 88626. https://reviews.llvm.org/D29964 Files: lldb/include/lldb/Host/PseudoTerminal.h lldb/include/lldb/Utility/PseudoTerminal.h lldb/include/lldb/Utility/VASPrintf.h lldb/source/Host/CMakeLists.txt lldb/source/Host/common/PseudoTerminal.cpp lldb/source/Utility/CMakeLists.txt lldb/source/Utility/Error.cpp lldb/source/Utility/PseudoTerminal.cpp lldb/source/Utility/Stream.cpp lldb/source/Utility/VASprintf.cpp lldb/unittests/Utility/CMakeLists.txt lldb/unittests/Utility/VASprintfTest.cpp Index: lldb/unittests/Utility/VASprintfTest.cpp === --- /dev/null +++ lldb/unittests/Utility/VASprintfTest.cpp @@ -0,0 +1,58 @@ +//===-- VASprintfTest.cpp ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "lldb/Utility/VASprintf.h" +#include "llvm/ADT/SmallString.h" + +#include "gtest/gtest.h" + +#include + +using namespace lldb_private; +using namespace llvm; + +static void Sprintf(llvm::SmallVectorImpl &Buffer, const char *Fmt, ...) { + va_list args; + va_start(args, Fmt); + VASprintf(Buffer, Fmt, args); + va_end(args); +} + +TEST(VASprintfTest, NoBufferResize) { + std::string TestStr("small"); + + llvm::SmallString<32> BigBuffer; + Sprintf(BigBuffer, "%s", TestStr.c_str()); + EXPECT_STREQ(TestStr.c_str(), BigBuffer.c_str()); + EXPECT_EQ(TestStr.size(), BigBuffer.size()); +} + +TEST(VASprintfTest, BufferResize) { + std::string TestStr("bigger"); + llvm::SmallString<4> SmallBuffer; + Sprintf(SmallBuffer, "%s", TestStr.c_str()); + EXPECT_STREQ(TestStr.c_str(), SmallBuffer.c_str()); + EXPECT_EQ(TestStr.size(), SmallBuffer.size()); +} + +TEST(VASprintfTest, EncodingError) { + // Save the current locale first. + std::string Current(::setlocale(LC_ALL, nullptr)); + + setlocale(LC_ALL, ".932"); + + wchar_t Invalid[2]; + Invalid[0] = 129; + Invalid[1] = 0; + llvm::SmallString<32> Buffer; + Sprintf(Buffer, "%ls", Invalid); + EXPECT_EQ("", Buffer); + + setlocale(LC_CTYPE, Current.c_str()); +} Index: lldb/unittests/Utility/CMakeLists.txt === --- lldb/unittests/Utility/CMakeLists.txt +++ lldb/unittests/Utility/CMakeLists.txt @@ -4,9 +4,9 @@ TaskPoolTest.cpp TimeoutTest.cpp UriParserTest.cpp + VASprintfTest.cpp LINK_LIBS - lldbHost lldbUtility LINK_COMPONENTS Support Index: lldb/source/Utility/VASprintf.cpp === --- /dev/null +++ lldb/source/Utility/VASprintf.cpp @@ -0,0 +1,52 @@ +//===-- VASPrintf.cpp ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--===// + +#include "lldb/Utility/VASprintf.h" + +#include "llvm/ADT/SmallString.h" + +using namespace lldb_private; + +bool lldb_private::VASprintf(llvm::SmallVectorImpl &buf, const char *fmt, + va_list args) { + llvm::SmallString<16> error(""); + bool result = true; + + // Copy in case our first call to vsnprintf doesn't fit into our buffer + va_list copy_args; + va_copy(copy_args, args); + + buf.resize(buf.capacity()); + // Write up to `capacity` bytes, ignoring the current size. + int length = ::vsnprintf(buf.data(), buf.size(), fmt, args); + if (length < 0) { +buf = error; +result = false; +goto finish; + } + + if (length >= buf.size()) { +// The error formatted string didn't fit into our buffer, resize it +// to the exact needed size, and retry +buf.resize(length + 1); +length = ::vsnprintf(buf.data(), buf.size(), fmt, copy_args); +if (length < 0) { + buf = error; + result = false; + goto finish; +} +assert(length < buf.size()); + } + buf.resize(length); + +finish: + va_end(args); + va_end(copy_args); + return result; +} Index: lldb/source/Utility/Stream.cpp === --- lldb/source/Utility/Stream.cpp +++ lldb/source/Utility/Stream.cpp @@ -8,8 +8,9 @@ //===--===// #include "lldb/Utility/Stream.h" -#include "lldb/Host/PosixApi.h" + #include "lldb/Utility/Endian.h" +#include "lldb/Utility/VASPrintf.h" #include #include #include @@ -162,36 +163,14 @@ // Print some formatted output to the stream. //-- size_t Stream::PrintfVarArg(const
[Lldb-commits] [lldb] r295271 - Fix a bug introduced in r235737 where code with important side
Author: jmolenda Date: Wed Feb 15 20:08:33 2017 New Revision: 295271 URL: http://llvm.org/viewvc/llvm-project?rev=295271&view=rev Log: Fix a bug introduced in r235737 where code with important side effects was passed as an expression to assert() calls. If lldb is built without asserts, the expression was eliminated and we lost the side effects -- these methods stopped working. Modified: lldb/trunk/source/Host/common/Symbols.cpp lldb/trunk/source/Host/macosx/Symbols.cpp Modified: lldb/trunk/source/Host/common/Symbols.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/Symbols.cpp?rev=295271&r1=295270&r2=295271&view=diff == --- lldb/trunk/source/Host/common/Symbols.cpp (original) +++ lldb/trunk/source/Host/common/Symbols.cpp Wed Feb 15 20:08:33 2017 @@ -54,7 +54,8 @@ static bool FileAtPathContainsArchAndUUI if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) { ModuleSpec spec; for (size_t i = 0; i < module_specs.GetSize(); ++i) { - assert(module_specs.GetModuleSpecAtIndex(i, spec)); + bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); + assert(got_spec); if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && (arch == NULL || (spec.GetArchitecturePtr() && spec.GetArchitecture().IsCompatibleMatch(*arch { Modified: lldb/trunk/source/Host/macosx/Symbols.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/macosx/Symbols.cpp?rev=295271&r1=295270&r2=295271&view=diff == --- lldb/trunk/source/Host/macosx/Symbols.cpp (original) +++ lldb/trunk/source/Host/macosx/Symbols.cpp Wed Feb 15 20:08:33 2017 @@ -263,7 +263,8 @@ FileSpec Symbols::FindSymbolFileInBundle module_specs)) { ModuleSpec spec; for (size_t i = 0; i < module_specs.GetSize(); ++i) { - assert(module_specs.GetModuleSpecAtIndex(i, spec)); + bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec); + assert(got_spec); if ((uuid == NULL || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) && (arch == NULL || ___ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D30024: [lldb] Add support for "external" reports in ThreadSanitizer LLDB plugin
kubamracek created this revision. TSan now has the ability to report races on "external" object, i.e. any library class/object that has read-shared write-exclusive threading semantics. The detection and reporting work almost out of the box, but TSan can now provide the type of the object (as a string). This patch implements this into LLDB. This is a new API in the TSan dylib, and we should still support cases the old dylib (that don't have the API), so the expression contains a call to dlsym to see if the new API is available or not. Let me know if there's a better solution. https://reviews.llvm.org/D30024 Files: source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp Index: source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp === --- source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp +++ source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp @@ -85,6 +85,9 @@ int *running, const char **name, int *parent_tid, void **trace, unsigned long trace_size); int __tsan_get_report_unique_tid(void *report, unsigned long idx, int *tid); + +void *dlsym(void* handle, const char* symbol); +int (*ptr__tsan_get_report_loc_object_type)(void *report, unsigned long idx, const char **object_type); } const int REPORT_TRACE_SIZE = 128; @@ -125,6 +128,7 @@ int fd; int suppressable; void *trace[REPORT_TRACE_SIZE]; +const char *object_type; } locs[REPORT_ARRAY_SIZE]; int mutex_count; @@ -158,6 +162,8 @@ const char *thread_sanitizer_retrieve_report_data_command = R"( data t = {0}; +ptr__tsan_get_report_loc_object_type = (typeof(ptr__tsan_get_report_loc_object_type))(void *)dlsym((void*)-2 /*RTLD_DEFAULT*/, "__tsan_get_report_loc_object_type"); + t.report = __tsan_get_current_report(); __tsan_get_report_data(t.report, &t.description, &t.report_count, &t.stack_count, &t.mop_count, &t.loc_count, &t.mutex_count, &t.thread_count, &t.unique_tid_count, t.sleep_trace, REPORT_TRACE_SIZE); @@ -177,6 +183,8 @@ for (int i = 0; i < t.loc_count; i++) { t.locs[i].idx = i; __tsan_get_report_loc(t.report, i, &t.locs[i].type, &t.locs[i].addr, &t.locs[i].start, &t.locs[i].size, &t.locs[i].tid, &t.locs[i].fd, &t.locs[i].suppressable, t.locs[i].trace, REPORT_TRACE_SIZE); +if (ptr__tsan_get_report_loc_object_type) +ptr__tsan_get_report_loc_object_type(t.report, i, &t.locs[i].object_type); } if (t.mutex_count > REPORT_ARRAY_SIZE) t.mutex_count = REPORT_ARRAY_SIZE; @@ -409,6 +417,8 @@ o->GetValueForExpressionPath(".suppressable") ->GetValueAsUnsigned(0)); dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); +dict->AddStringItem("object_type", +RetrieveString(o, process_sp, ".object_type")); }); dict->AddItem("locs", StructuredData::ObjectSP(locs)); @@ -511,6 +521,8 @@ return "Overwrite of errno in a signal handler"; } else if (description == "lock-order-inversion") { return "Lock order inversion (potential deadlock)"; + } else if (description == "external-race") { +return "Race on a library object"; } // for unknown report codes just show the code @@ -634,6 +646,13 @@ ->GetValueForKey("locs") ->GetAsArray() ->GetItemAtIndex(0); +std::string object_type = loc->GetAsDictionary() + ->GetValueForKey("object_type") + ->GetAsString() + ->GetValue(); +if (!object_type.empty()) { + summary = "Race on " + object_type + " object"; +} addr_t addr = loc->GetAsDictionary() ->GetValueForKey("address") ->GetAsInteger() @@ -726,8 +745,17 @@ ->GetValueForKey("size") ->GetAsInteger() ->GetValue(); - result = - Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); + std::string object_type = loc->GetAsDictionary() +->GetValueForKey("object_type") +->GetAsString() +->GetValue(); + if (!object_type.empty()) { +result = Sprintf("Location is a %ld-byte %s object at 0x%llx", size, + object_type.c_str(), addr); + } else { +result = +Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); + } } else if (type == "stack") { int tid = loc->GetAsDictionary()