From gclayton at apple.com Tue Jul 5 12:46:40 2011 From: gclayton at apple.com (Greg Clayton) Date: Tue, 05 Jul 2011 17:46:40 -0000 Subject: [Lldb-commits] [lldb] r134420 - /lldb/tags/lldb-67/ Message-ID: <20110705174640.CD72F2A6C12C@llvm.org> Author: gclayton Date: Tue Jul 5 12:46:40 2011 New Revision: 134420 URL: http://llvm.org/viewvc/llvm-project?rev=134420&view=rev Log: Preparing for lldb-67 submissions. No changes from lldb-66, just going to resubmit with needed build files. Added: lldb/tags/lldb-67/ - copied from r134419, lldb/tags/lldb-66/ From gclayton at apple.com Tue Jul 5 12:50:58 2011 From: gclayton at apple.com (Greg Clayton) Date: Tue, 05 Jul 2011 17:50:58 -0000 Subject: [Lldb-commits] [lldb] r134421 - in /lldb/tags/lldb-67: lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist Message-ID: <20110705175058.C02602A6C12C@llvm.org> Author: gclayton Date: Tue Jul 5 12:50:58 2011 New Revision: 134421 URL: http://llvm.org/viewvc/llvm-project?rev=134421&view=rev Log: lldb-67 Modified: lldb/tags/lldb-67/lldb.xcodeproj/project.pbxproj lldb/tags/lldb-67/resources/LLDB-Info.plist Modified: lldb/tags/lldb-67/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-67/lldb.xcodeproj/project.pbxproj?rev=134421&r1=134420&r2=134421&view=diff ============================================================================== --- lldb/tags/lldb-67/lldb.xcodeproj/project.pbxproj (original) +++ lldb/tags/lldb-67/lldb.xcodeproj/project.pbxproj Tue Jul 5 12:50:58 2011 @@ -3412,10 +3412,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 67; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3464,11 +3464,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 67; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3515,8 +3515,8 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; - DYLIB_CURRENT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; + DYLIB_CURRENT_VERSION = 67; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3554,9 +3554,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 67; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3594,9 +3594,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 67; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3664,7 +3664,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3695,11 +3695,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 67; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3824,7 +3824,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEBUG_INFORMATION_FORMAT = dwarf; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3856,7 +3856,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 67; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", Modified: lldb/tags/lldb-67/resources/LLDB-Info.plist URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-67/resources/LLDB-Info.plist?rev=134421&r1=134420&r2=134421&view=diff ============================================================================== --- lldb/tags/lldb-67/resources/LLDB-Info.plist (original) +++ lldb/tags/lldb-67/resources/LLDB-Info.plist Tue Jul 5 12:50:58 2011 @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 66 + 67 CFBundleName ${EXECUTABLE_NAME} From johnny.chen at apple.com Tue Jul 5 14:18:42 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 05 Jul 2011 19:18:42 -0000 Subject: [Lldb-commits] [lldb] r134437 - in /lldb/trunk/include/lldb/API: SBProcess.h SBSymbolContext.h Message-ID: <20110705191842.264922A6C12C@llvm.org> Author: johnny Date: Tue Jul 5 14:18:41 2011 New Revision: 134437 URL: http://llvm.org/viewvc/llvm-project?rev=134437&view=rev Log: Add a more verbose docstring to the SBSymbolContext API class. Add doxygen/docstring to SBProcess.RemoteAttachToProcessWithID() API method. Modified: lldb/trunk/include/lldb/API/SBProcess.h lldb/trunk/include/lldb/API/SBSymbolContext.h Modified: lldb/trunk/include/lldb/API/SBProcess.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBProcess.h?rev=134437&r1=134436&r2=134437&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBProcess.h (original) +++ lldb/trunk/include/lldb/API/SBProcess.h Tue Jul 5 14:18:41 2011 @@ -80,11 +80,17 @@ void AppendEventStateReport (const lldb::SBEvent &event, lldb::SBCommandReturnObject &result); +#ifdef SWIG + %feature("docstring", " +#endif //------------------------------------------------------------------ - // Remote connection related functions. These will fail if the - // process is not in eStateConnected. They are intended for use - // when connecting to an externally managed debugserver instance. + /// Remote connection related functions. These will fail if the + /// process is not in eStateConnected. They are intended for use + /// when connecting to an externally managed debugserver instance. //------------------------------------------------------------------ +#ifdef SWIG + ") RemoteAttachToProcessWithID; +#endif bool RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error); Modified: lldb/trunk/include/lldb/API/SBSymbolContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBSymbolContext.h?rev=134437&r1=134436&r2=134437&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBSymbolContext.h (original) +++ lldb/trunk/include/lldb/API/SBSymbolContext.h Tue Jul 5 14:18:41 2011 @@ -22,7 +22,41 @@ #ifdef SWIG %feature("docstring", - "A container that stores various debugger related info." +"A context object that provides access to core debugger entities. + +Manay debugger functions require a context when doing lookups. This class +provides a common structure that can be used as the result of a query that +can contain a single result. + +For example, + + exe = os.path.join(os.getcwd(), 'a.out') + + # Create a target for the debugger. + target = self.dbg.CreateTarget(exe) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + + # The inferior should stop on 'c'. + from lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + frame0 = thread.GetFrameAtIndex(0) + + # Now get the SBSymbolContext from this frame. We want everything. :-) + context = frame0.GetSymbolContext(lldb.eSymbolContextEverything) + + # Get the module. + module = context.GetModule() + ... + + # And the compile unit associated with the frame. + compileUnit = context.GetCompileUnit() + ... +" ) SBSymbolContext; #endif class SBSymbolContext From johnny.chen at apple.com Tue Jul 5 17:03:36 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 05 Jul 2011 22:03:36 -0000 Subject: [Lldb-commits] [lldb] r134446 - in /lldb/trunk: include/lldb/API/SBModule.h include/lldb/Core/Module.h test/python_api/default-constructor/sb_module.py Message-ID: <20110705220337.034A02A6C12C@llvm.org> Author: johnny Date: Tue Jul 5 17:03:36 2011 New Revision: 134446 URL: http://llvm.org/viewvc/llvm-project?rev=134446&view=rev Log: Add swig docstrings for SBModule.h, plus ifndef the SBModule::GetUUIDBytes() API out if swig. Fix typos in the comment for Module.h. Modified: lldb/trunk/include/lldb/API/SBModule.h lldb/trunk/include/lldb/Core/Module.h lldb/trunk/test/python_api/default-constructor/sb_module.py Modified: lldb/trunk/include/lldb/API/SBModule.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBModule.h?rev=134446&r1=134445&r2=134446&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBModule.h (original) +++ lldb/trunk/include/lldb/API/SBModule.h Tue Jul 5 17:03:36 2011 @@ -19,7 +19,11 @@ #ifdef SWIG %feature("docstring", "Represents an executable image and its associated object and symbol" - " files." + " files.\n" + "\n" + "The module is designed to be able to select a single slice of an\n" + "executable image as it would appear on disk and during program\n" + "execution." ) SBModule; #endif class SBModule @@ -44,18 +48,62 @@ bool IsValid () const; +#ifdef SWIG + %feature("autodoc", " +#endif + //------------------------------------------------------------------ + /// Get const accessor for the module file specification. + /// + /// This function returns the file for the module on the host system + /// that is running LLDB. This can differ from the path on the + /// platform since we might be doing remote debugging. + /// + /// @return + /// A const reference to the file specification object. + //------------------------------------------------------------------ +#ifdef SWIG + ") GetFileSpec; +#endif lldb::SBFileSpec GetFileSpec () const; +#ifdef SWIG + %feature("autodoc", " +#endif + //------------------------------------------------------------------ + /// Get accessor for the module platform file specification. + /// + /// Platform file refers to the path of the module as it is known on + /// the remote system on which it is being debugged. For local + /// debugging this is always the same as Module::GetFileSpec(). But + /// remote debugging might mention a file '/usr/lib/liba.dylib' + /// which might be locally downloaded and cached. In this case the + /// platform file could be something like: + /// '/tmp/lldb/platform-cache/remote.host.computer/usr/lib/liba.dylib' + /// The file could also be cached in a local developer kit directory. + /// + /// @return + /// A const reference to the file specification object. + //------------------------------------------------------------------ +#ifdef SWIG + ") GetPlatformFileSpec; +#endif lldb::SBFileSpec GetPlatformFileSpec () const; bool SetPlatformFileSpec (const lldb::SBFileSpec &platform_file); +#ifndef SWIG const uint8_t * GetUUIDBytes () const; +#endif +#ifdef SWIG + %feature("autodoc", + "Returns the UUID of the module as a Python string." + ) GetUUIDString; +#endif const char * GetUUIDString () const; @@ -85,12 +133,61 @@ lldb::SBSymbol GetSymbolAtIndex (size_t idx); +#ifdef SWIG + %feature("autodoc", " +#endif + //------------------------------------------------------------------ + /// Find functions by name. + /// + /// @param[in] name + /// The name of the function we are looking for. + /// + /// @param[in] name_type_mask + /// A logical OR of one or more FunctionNameType enum bits that + /// indicate what kind of names should be used when doing the + /// lookup. Bits include fully qualified names, base names, + /// C++ methods, or ObjC selectors. + /// See FunctionNameType for more details. + /// + /// @param[in] append + /// If true, any matches will be appended to \a sc_list, else + /// matches replace the contents of \a sc_list. + /// + /// @param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// + /// @return + /// The number of matches added to \a sc_list. + //------------------------------------------------------------------ +#ifdef SWIG + ") FindFunctions; +#endif uint32_t FindFunctions (const char *name, uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits bool append, lldb::SBSymbolContextList& sc_list); +#ifdef SWIG + %feature("autodoc", " +#endif + //------------------------------------------------------------------ + /// Find global and static variables by name. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @param[in] target + /// The target program where the variables reside. + /// + /// @return + /// A list of matched variables in an SBValueList. + //------------------------------------------------------------------ +#ifdef SWIG + ") FindGlobalVariables; +#endif lldb::SBValueList FindGlobalVariables (lldb::SBTarget &target, const char *name, Modified: lldb/trunk/include/lldb/Core/Module.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=134446&r1=134445&r2=134446&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Module.h (original) +++ lldb/trunk/include/lldb/Core/Module.h Tue Jul 5 17:03:36 2011 @@ -169,9 +169,8 @@ /// See FunctionNameType for more details. /// /// @param[in] append - /// If \b true, any matches will be appended to \a - /// variable_list, else matches replace the contents of - /// \a variable_list. + /// If \b true, any matches will be appended to \a sc_list, else + /// matches replace the contents of \a sc_list. /// /// @param[out] sc_list /// A symbol context list that gets filled in with all of the @@ -194,9 +193,8 @@ /// A regular expression to use when matching the name. /// /// @param[in] append - /// If \b true, any matches will be appended to \a - /// variable_list, else matches replace the contents of - /// \a variable_list. + /// If \b true, any matches will be appended to \a sc_list, else + /// matches replace the contents of \a sc_list. /// /// @param[out] sc_list /// A symbol context list that gets filled in with all of the Modified: lldb/trunk/test/python_api/default-constructor/sb_module.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/default-constructor/sb_module.py?rev=134446&r1=134445&r2=134446&view=diff ============================================================================== --- lldb/trunk/test/python_api/default-constructor/sb_module.py (original) +++ lldb/trunk/test/python_api/default-constructor/sb_module.py Tue Jul 5 17:03:36 2011 @@ -9,7 +9,6 @@ obj.GetFileSpec() obj.GetPlatformFileSpec() obj.SetPlatformFileSpec(lldb.SBFileSpec()) - obj.GetUUIDBytes() obj.GetUUIDString() obj.ResolveFileAddress(sys.maxint, lldb.SBAddress()) obj.ResolveSymbolContextForAddress(lldb.SBAddress(), 0) From johnny.chen at apple.com Tue Jul 5 18:54:12 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 05 Jul 2011 23:54:12 -0000 Subject: [Lldb-commits] [lldb] r134451 - /lldb/trunk/include/lldb/API/SBBlock.h Message-ID: <20110705235412.2D7BD2A6C12C@llvm.org> Author: johnny Date: Tue Jul 5 18:54:12 2011 New Revision: 134451 URL: http://llvm.org/viewvc/llvm-project?rev=134451&view=rev Log: Add swig docstrings for SBBlock.h. Modified: lldb/trunk/include/lldb/API/SBBlock.h Modified: lldb/trunk/include/lldb/API/SBBlock.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBlock.h?rev=134451&r1=134450&r2=134451&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBBlock.h (original) +++ lldb/trunk/include/lldb/API/SBBlock.h Tue Jul 5 18:54:12 2011 @@ -37,30 +37,68 @@ operator = (const lldb::SBBlock &rhs); #endif +#ifdef SWIG + %feature("docstring", + "Does this block represent an inlined function?" + ) IsInlined; +#endif bool IsInlined () const; bool IsValid () const; +#ifdef SWIG + %feature("autodoc", + "Get the function name if this block represents an inlined function;\n" + "otherwise, return None." + ) GetInlinedName; +#endif const char * GetInlinedName () const; +#ifdef SWIG + %feature("docstring", + "Get the call site file if this block represents an inlined function;\n" + "otherwise, return an invalid file spec." + ) GetInlinedCallSiteFile; +#endif lldb::SBFileSpec GetInlinedCallSiteFile () const; +#ifdef SWIG + %feature("docstring", + "Get the call site line if this block represents an inlined function;\n" + "otherwise, return 0." + ) GetInlinedCallSiteLine; +#endif uint32_t GetInlinedCallSiteLine () const; +#ifdef SWIG + %feature("docstring", + "Get the call site column if this block represents an inlined function;\n" + "otherwise, return 0." + ) GetInlinedCallSiteColumn; +#endif uint32_t GetInlinedCallSiteColumn () const; +#ifdef SWIG + %feature("docstring", "Get the parent block.") GetParent; +#endif lldb::SBBlock GetParent (); +#ifdef SWIG + %feature("docstring", "Get the sibling block for this block.") GetSibling; +#endif lldb::SBBlock GetSibling (); +#ifdef SWIG + %feature("docstring", "Get the first child block.") GetFirstChild; +#endif lldb::SBBlock GetFirstChild (); From johnny.chen at apple.com Tue Jul 5 19:16:21 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 06 Jul 2011 00:16:21 -0000 Subject: [Lldb-commits] [lldb] r134452 - /lldb/trunk/include/lldb/API/SBThread.h Message-ID: <20110706001621.838542A6C12C@llvm.org> Author: johnny Date: Tue Jul 5 19:16:21 2011 New Revision: 134452 URL: http://llvm.org/viewvc/llvm-project?rev=134452&view=rev Log: Add a more verbose docstring for SBThread.h. Modified: lldb/trunk/include/lldb/API/SBThread.h Modified: lldb/trunk/include/lldb/API/SBThread.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=134452&r1=134451&r2=134452&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBThread.h (original) +++ lldb/trunk/include/lldb/API/SBThread.h Tue Jul 5 19:16:21 2011 @@ -20,8 +20,27 @@ #ifdef SWIG %feature("docstring", - "Represents a thread of execution." - " SBProcess contains SBThread(s)." +"Represents a thread of execution. SBProcess contains SBThread(s). + +For example (in test/lldbutil.py), + +# ================================================== +# Utility functions related to Threads and Processes +# ================================================== + +def get_stopped_threads(process, reason): + '''Returns the thread(s) with the specified stop reason in a list. + + The list can be empty if no such thread exists. + ''' + threads = [] + for t in process: + if t.GetStopReason() == reason: + threads.append(t) + return threads + +... +" ) SBThread; #endif class SBThread @@ -46,27 +65,40 @@ lldb::StopReason GetStopReason(); - // Get the number of words associated with the stop reason. +#ifdef SWIG + %feature("docstring", " +#endif + /// Get the number of words associated with the stop reason. + /// See also GetStopReasonDataAtIndex(). +#ifdef SWIG + ") GetStopReasonDataCount; +#endif size_t GetStopReasonDataCount(); +#ifdef SWIG + %feature("docstring", " +#endif //-------------------------------------------------------------------------- - // Get information associated with a stop reason. - // - // Breakpoint stop reasons will have data that consists of pairs of - // breakpoint IDs followed by the breakpoint location IDs (they always come - // in pairs). - // - // Stop Reason Count Data Type - // ======================== ===== ========================================== - // eStopReasonNone 0 - // eStopReasonTrace 0 - // eStopReasonBreakpoint N duple: {breakpoint id, location id} - // eStopReasonWatchpoint N duple: {watchpoint id, location id} - // eStopReasonSignal 1 unix signal number - // eStopReasonException N exception data - // eStopReasonPlanComplete 0 + /// Get information associated with a stop reason. + /// + /// Breakpoint stop reasons will have data that consists of pairs of + /// breakpoint IDs followed by the breakpoint location IDs (they always come + /// in pairs). + /// + /// Stop Reason Count Data Type + /// ======================== ===== ========================================= + /// eStopReasonNone 0 + /// eStopReasonTrace 0 + /// eStopReasonBreakpoint N duple: {breakpoint id, location id} + /// eStopReasonWatchpoint N duple: {watchpoint id, location id} + /// eStopReasonSignal 1 unix signal number + /// eStopReasonException N exception data + /// eStopReasonPlanComplete 0 //-------------------------------------------------------------------------- +#ifdef SWIG + ") GetStopReasonDataAtIndex; +#endif uint64_t GetStopReasonDataAtIndex(uint32_t idx); @@ -108,27 +140,33 @@ void RunToAddress (lldb::addr_t addr); +#ifdef SWIG + %feature("docstring", " +#endif //-------------------------------------------------------------------------- - // LLDB currently supports process centric debugging which means when any - // thread in a process stops, all other threads are stopped. The Suspend() - // call here tells our process to suspend a thread and not let it run when - // the other threads in a process are allowed to run. So when - // SBProcess::Continue() is called, any threads that aren't suspended will - // be allowed to run. If any of the SBThread functions for stepping are - // called (StepOver, StepInto, StepOut, StepInstruction, RunToAddres), the - // thread will now be allowed to run and these funtions will simply return. - // - // Eventually we plan to add support for thread centric debugging where each - // thread is controlled individually and each thread would broadcast its - // state, but we haven't implemented this yet. - // - // Likewise the SBThread::Resume() call will again allow the thread to run - // when the process is continued. - // - // The Suspend() and Resume() functions are not currently reference counted, - // if anyone has the need for them to be reference counted, please let us - // know. + /// LLDB currently supports process centric debugging which means when any + /// thread in a process stops, all other threads are stopped. The Suspend() + /// call here tells our process to suspend a thread and not let it run when + /// the other threads in a process are allowed to run. So when + /// SBProcess::Continue() is called, any threads that aren't suspended will + /// be allowed to run. If any of the SBThread functions for stepping are + /// called (StepOver, StepInto, StepOut, StepInstruction, RunToAddres), the + /// thread will now be allowed to run and these funtions will simply return. + /// + /// Eventually we plan to add support for thread centric debugging where + /// each thread is controlled individually and each thread would broadcast + /// its state, but we haven't implemented this yet. + /// + /// Likewise the SBThread::Resume() call will again allow the thread to run + /// when the process is continued. + /// + /// Suspend() and Resume() functions are not currently reference counted, if + /// anyone has the need for them to be reference counted, please let us + /// know. //-------------------------------------------------------------------------- +#ifdef SWIG + ") Suspend; +#endif bool Suspend(); From granata.enrico at gmail.com Tue Jul 5 21:13:41 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Wed, 06 Jul 2011 02:13:41 -0000 Subject: [Lldb-commits] [lldb] r134458 - in /lldb/trunk: include/lldb/Core/ include/lldb/Symbol/ lldb.xcodeproj/ source/Core/ source/Symbol/ source/Target/ test/functionalities/data-formatter/data-formatter-advanced/ test/functionalities/data-formatter/data-formatter-cpp/ Message-ID: <20110706021341.7C09E2A6C12C@llvm.org> Author: enrico Date: Tue Jul 5 21:13:41 2011 New Revision: 134458 URL: http://llvm.org/viewvc/llvm-project?rev=134458&view=rev Log: new syntax for summary strings: - ${*expr} now simply means to dereference expr before actually using it - bitfields, array ranges and pointer ranges now work in a (hopefully) more natural and language-compliant way a new class TypeHierarchyNavigator replicates the behavior of the FormatManager in going through type hierarchies when one-lining summary strings, children's summaries can be used as well as values Added: lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp Modified: lldb/trunk/include/lldb/Core/FormatManager.h lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Symbol/ClangASTContext.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Core/DataExtractor.cpp lldb/trunk/source/Core/Debugger.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Symbol/ClangASTContext.cpp lldb/trunk/source/Target/StackFrame.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Modified: lldb/trunk/include/lldb/Core/FormatManager.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FormatManager.h?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/FormatManager.h (original) +++ lldb/trunk/include/lldb/Core/FormatManager.h Tue Jul 5 21:13:41 2011 @@ -260,6 +260,13 @@ if (!typePtr) return false; ConstString name(ClangASTType::GetTypeNameForQualType(type).c_str()); + if(vobj.GetBitfieldBitSize() > 0) + { + // for bitfields, append size to the typename so one can custom format them + StreamString sstring; + sstring.Printf("%s:%d",name.AsCString(),vobj.GetBitfieldBitSize()); + name = ConstString(sstring.GetData()); + } //printf("trying to get format for VO name %s of type %s\n",vobj.GetName().AsCString(),name.AsCString()); if (Get(name.GetCString(), entry)) return true; @@ -357,8 +364,7 @@ template<> bool FormatNavigator, SummaryFormat::RegexSummaryCallback>::Get(const char* key, - SummaryFormat::SharedPointer& value); - + SummaryFormat::SharedPointer& value); template<> bool FormatNavigator, SummaryFormat::RegexSummaryCallback>::Delete(const char* type); Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Tue Jul 5 21:13:41 2011 @@ -246,6 +246,9 @@ virtual bool IsPointerType (); + + virtual bool + IsScalarType (); virtual bool IsPointerOrReferenceType (); @@ -302,6 +305,12 @@ } virtual bool + IsArrayItemForPointer() + { + return m_is_array_item_for_pointer; + } + + virtual bool SetClangAST (clang::ASTContext *ast) { return false; @@ -357,6 +366,10 @@ lldb::Format custom_format = lldb::eFormatInvalid); bool + DumpPrintableRepresentation(Stream& s, + ValueObjectRepresentationStyle val_obj_display = eDisplaySummary, + lldb::Format custom_format = lldb::eFormatInvalid); + bool GetValueIsValid () const; bool @@ -392,6 +405,9 @@ GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create); lldb::ValueObjectSP + GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create); + + lldb::ValueObjectSP GetDynamicValue (lldb::DynamicValueType valueType); virtual lldb::ValueObjectSP @@ -537,7 +553,8 @@ m_old_value_valid:1, m_pointers_point_to_load_addrs:1, m_is_deref_of_parent:1, - m_is_array_item_for_pointer:1; + m_is_array_item_for_pointer:1, + m_is_bitfield_for_scalar:1; friend class ClangExpressionDeclMap; // For GetValue friend class ClangExpressionVariable; // For SetName Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original) +++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Tue Jul 5 21:13:41 2011 @@ -661,8 +661,19 @@ //------------------------------------------------------------------ static bool IsFloatingPointType (lldb::clang_type_t clang_type, uint32_t &count, bool &is_complex); + + // true iff this is one of the types that can "fit" + // in a Scalar object + static bool + IsScalarType (lldb::clang_type_t clang_type); + + static bool + IsPointerToScalarType (lldb::clang_type_t clang_type); static bool + IsArrayOfScalarType (lldb::clang_type_t clang_type); + + static bool GetCXXClassName (lldb::clang_type_t clang_type, std::string &class_name); Added: lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h?rev=134458&view=auto ============================================================================== --- lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h (added) +++ lldb/trunk/include/lldb/Symbol/TypeHierarchyNavigator.h Tue Jul 5 21:13:41 2011 @@ -0,0 +1,75 @@ +//===-- TypeHierarchyNavigator.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_TypeHierarchyNavigator_h_ +#define lldb_TypeHierarchyNavigator_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" +#include "clang/AST/DeclObjC.h" + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +namespace lldb_private { + +class TypeHierarchyNavigator { + +public: + + enum RelationshipToCurrentType + { + eRootType, + eCXXBaseClass, + eCXXVBaseClass, + eObjCBaseClass, + eStrippedPointer, + eStrippedReference, + eStrippedTypedef + }; + + typedef bool (*TypeHierarchyNavigatorCallback)(const clang::QualType& qual_type, + RelationshipToCurrentType reason_why_here, + void* callback_baton); + + TypeHierarchyNavigator(const clang::QualType& qual_type, + ValueObject& val_obj, + void* callback_baton = NULL) : + m_root_type(qual_type), + m_value_object(val_obj), + m_default_callback_baton(callback_baton) + { + } + + bool + LoopThrough(TypeHierarchyNavigatorCallback callback, + void* callback_baton = NULL); + +private: + + bool + LoopThrough(const clang::QualType& qual_type, + TypeHierarchyNavigatorCallback callback, + RelationshipToCurrentType reason_why_here, + void* callback_baton); + + const clang::QualType& m_root_type; + ValueObject& m_value_object; + void* m_default_callback_baton; + +}; + +} // namespace lldb_private + +#endif // lldb_TypeHierarchyNavigator_h_ Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Tue Jul 5 21:13:41 2011 @@ -402,6 +402,7 @@ 4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; }; 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; }; 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */; }; + 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */; }; 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; }; 9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */; }; @@ -1165,6 +1166,8 @@ 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FormatManager.cpp; path = source/Core/FormatManager.cpp; sourceTree = ""; }; 9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectType.cpp; path = source/Commands/CommandObjectType.cpp; sourceTree = ""; }; 9463D4CE13B179A500C230D4 /* CommandObjectType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectType.h; path = source/Commands/CommandObjectType.h; sourceTree = ""; }; + 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeHierarchyNavigator.cpp; path = source/Symbol/TypeHierarchyNavigator.cpp; sourceTree = ""; }; + 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = TypeHierarchyNavigator.h; path = include/lldb/Symbol/TypeHierarchyNavigator.h; sourceTree = ""; }; 961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = ""; }; 961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = ""; }; 961FABBA1235DE1600F93A47 /* UnwindTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindTable.cpp; path = source/Symbol/UnwindTable.cpp; sourceTree = ""; }; @@ -2043,6 +2046,8 @@ 49BB309511F79450001A4197 /* TaggedASTType.h */, 26BC7C6510F1B6E900F91463 /* Type.h */, 26BC7F2010F1B8EC00F91463 /* Type.cpp */, + 9467E65413C3D98900B3B6F3 /* TypeHierarchyNavigator.h */, + 9467E65113C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp */, 26BC7C6610F1B6E900F91463 /* TypeList.h */, 26BC7F2110F1B8EC00F91463 /* TypeList.cpp */, 269FF07F12494F8E00225026 /* UnwindPlan.h */, @@ -3239,6 +3244,7 @@ 9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */, 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */, 49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */, + 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Modified: lldb/trunk/source/Core/DataExtractor.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataExtractor.cpp?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/source/Core/DataExtractor.cpp (original) +++ lldb/trunk/source/Core/DataExtractor.cpp Tue Jul 5 21:13:41 2011 @@ -753,7 +753,9 @@ { if (bitfield_bit_offset > 0) uval64 >>= bitfield_bit_offset; - uint64_t bitfield_mask = ((1 << bitfield_bit_size) - 1); + uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1); + if(!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64) + return uval64; uval64 &= bitfield_mask; } return uval64; Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Tue Jul 5 21:13:41 2011 @@ -694,6 +694,176 @@ } } +// #define VERBOSE_FORMATPROMPT_OUTPUT +#ifdef VERBOSE_FORMATPROMPT_OUTPUT +#define IFERROR_PRINT_IT if (error.Fail()) \ +{ \ + printf("ERROR: %s\n",error.AsCString("unknown")); \ + break; \ +} +#else // IFERROR_PRINT_IT +#define IFERROR_PRINT_IT if (error.Fail()) \ +break; +#endif // IFERROR_PRINT_IT + +static bool +ScanFormatDescriptor(const char* var_name_begin, + const char* var_name_end, + const char** var_name_final, + const char** percent_position, + lldb::Format* custom_format, + ValueObject::ValueObjectRepresentationStyle* val_obj_display) +{ + *percent_position = ::strchr(var_name_begin,'%'); + if(!*percent_position || *percent_position > var_name_end) + *var_name_final = var_name_end; + else + { + *var_name_final = *percent_position; + char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0'; + memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1); + if ( !FormatManager::GetFormatFromCString(format_name, + true, + *custom_format) ) + { + // if this is an @ sign, print ObjC description + if(*format_name == '@') + *val_obj_display = ValueObject::eDisplayLanguageSpecific; + // if this is a V, print the value using the default format + if(*format_name == 'V') + *val_obj_display = ValueObject::eDisplayValue; + } + // a good custom format tells us to print the value using it + else + *val_obj_display = ValueObject::eDisplayValue; + delete format_name; + } + return true; +} + +static bool +ScanBracketedRange(const char* var_name_begin, + const char* var_name_end, + const char* var_name_final, + const char** open_bracket_position, + const char** separator_position, + const char** close_bracket_position, + const char** var_name_final_if_array_range, + int64_t* index_lower, + int64_t* index_higher) +{ + *open_bracket_position = ::strchr(var_name_begin,'['); + if(*open_bracket_position && *open_bracket_position < var_name_final) + { + *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield + *close_bracket_position = ::strchr(*open_bracket_position,']'); + // as usual, we assume that [] will come before % + //printf("trying to expand a []\n"); + *var_name_final_if_array_range = *open_bracket_position; + if(*close_bracket_position - *open_bracket_position == 1) + { + *index_lower = 0; + } + else if (*separator_position == NULL || *separator_position > var_name_end) + { + char *end = NULL; + *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); + *index_higher = *index_lower; + //printf("got to read low=%d high same\n",bitfield_lower); + } + else if(*close_bracket_position && *close_bracket_position < var_name_end) + { + char *end = NULL; + *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); + *index_higher = ::strtoul (*separator_position+1, &end, 0); + //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher); + } + else + return false; + if (*index_lower > *index_higher && *index_higher > 0) + { + int temp = *index_lower; + *index_lower = *index_higher; + *index_higher = temp; + } + } + return true; +} + + +static ValueObjectSP +ExpandExpressionPath(ValueObject* vobj, + StackFrame* frame, + bool* do_deref_pointer, + const char* var_name_begin, + const char* var_name_final, + Error& error) +{ + + StreamString sstring; + VariableSP var_sp; + + if(*do_deref_pointer) + sstring.PutChar('*'); + else if(vobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(vobj->GetParent()->GetClangType()) && !vobj->IsArrayItemForPointer()) + { + sstring.PutChar('*'); + *do_deref_pointer = true; + } + + vobj->GetExpressionPath(sstring, true, ValueObject::eHonorPointers); +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("name to expand in phase 0: %s\n",sstring.GetData()); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3); +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("name to expand in phase 1: %s\n",sstring.GetData()); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + std::string name = std::string(sstring.GetData()); + ValueObjectSP target = frame->GetValueForVariableExpressionPath (name.c_str(), + eNoDynamicValues, + 0, + var_sp, + error); + return target; +} + +static ValueObjectSP +ExpandIndexedExpression(ValueObject* vobj, + uint32_t index, + StackFrame* frame, + Error error) +{ + ValueObjectSP item; + bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType()); + + if(is_array) + return vobj->GetChildAtIndex(index, true); + else + { + const char* ptr_deref_format = "%s[%d]"; + char* ptr_deref_buffer = new char[1024]; + StreamString expr_path_string; + vobj->GetExpressionPath(expr_path_string, true, ValueObject::eHonorPointers); + const char* expr_path = expr_path_string.GetData(); +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("name to deref in phase 0: %s\n",expr_path); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + ::sprintf(ptr_deref_buffer, ptr_deref_format, expr_path, index); +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("name to deref in phase 1: %s\n",ptr_deref_buffer); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + lldb::VariableSP var_sp; + item = frame->GetValueForVariableExpressionPath (ptr_deref_buffer, + eNoDynamicValues, + 0, + var_sp, + error); + delete ptr_deref_buffer; + } + return item; +} + bool Debugger::FormatPrompt ( @@ -783,6 +953,7 @@ FileSpec format_file_spec; const RegisterInfo *reg_info = NULL; RegisterContext *reg_ctx = NULL; + bool do_deref_pointer = false; // Each variable must set success to true below... bool var_success = false; @@ -791,270 +962,19 @@ case '*': { if (!vobj) break; - lldb::clang_type_t pointer_clang_type = vobj->GetClangType(); - clang_type_t elem_or_pointee_clang_type; - const Flags type_flags (ClangASTContext::GetTypeInfo (pointer_clang_type, - vobj->GetClangAST(), - &elem_or_pointee_clang_type)); - bool is_pointer = type_flags.Test (ClangASTContext::eTypeIsPointer), - is_array = type_flags.Test (ClangASTContext::eTypeIsArray); - if ( is_array || - ( is_pointer && ::strchr(var_name_begin,'[') && ::strchr(var_name_begin,'[') < var_name_end ) - ) - { - const char* var_name_final; - const char* close_bracket_position = NULL; - const char* percent_position = NULL; - const char* targetvalue; - lldb::Format custom_format = eFormatInvalid; - int index_lower = -1; - int index_higher = -1; - ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary; - { - percent_position = ::strchr(var_name_begin,'%'); - if(!percent_position || percent_position > var_name_end) - var_name_final = var_name_end; - else - { - var_name_final = percent_position; - char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0'; - memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1); - if ( !FormatManager::GetFormatFromCString(format_name, - true, - custom_format) ) - { - // if this is an @ sign, print ObjC description - if(*format_name == '@') - val_obj_display = ValueObject::eDisplayLanguageSpecific; - // if this is a V, print the value using the default format - if(*format_name == 'V') - val_obj_display = ValueObject::eDisplayValue; - } - // a good custom format tells us to print the value using it - else - val_obj_display = ValueObject::eDisplayValue; - } - } - - { - const char* open_bracket_position = ::strchr(var_name_begin,'['); - if(open_bracket_position && open_bracket_position < var_name_final) - { - // TODO: pick a way to say "all entries". this will make more sense once - // regex typenames are in place. now, you need to be size-aware anyways - const char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield - close_bracket_position = ::strchr(open_bracket_position,']'); - // as usual, we assume that [] will come before % - //printf("trying to expand a []\n"); - var_name_final = open_bracket_position; - if(close_bracket_position - open_bracket_position == 1) - { - if(is_array) - { - index_lower = 0; - index_higher = vobj->GetNumChildren() - 1; - } - else - break; // cannot auto-determine size for pointers - } - else if (separator_position == NULL || separator_position > var_name_end) - { - char *end = NULL; - index_lower = ::strtoul (open_bracket_position+1, &end, 0); - index_higher = index_lower; - //printf("got to read low=%d high same\n",bitfield_lower); - } - else if(close_bracket_position && close_bracket_position < var_name_end) - { - char *end = NULL; - index_lower = ::strtoul (open_bracket_position+1, &end, 0); - index_higher = ::strtoul (separator_position+1, &end, 0); - //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher); - } - else - break; - if (index_lower > index_higher) - { - int temp = index_lower; - index_lower = index_higher; - index_higher = temp; - } - //*((char*)open_bracket_position) = '\0'; - //printf("variable name is %s\n",var_name_begin); - //*((char*)open_bracket_position) = '['; - } - } - - // if you just type a range, lldb will do the "right thing" in picking - // a reasonable display for the array entries. you can override this by - // giving other input (e.g. ${*var[1-3].member1%uint8_t[]}) and they - // will be honored - char* special_directions = NULL; - if (close_bracket_position && (var_name_end-close_bracket_position > 1)) - { - int base_len = var_name_end-close_bracket_position; - special_directions = new char[8+base_len]; - special_directions[0] = '$'; - special_directions[1] = '{'; - special_directions[2] = 'v'; - special_directions[3] = 'a'; - special_directions[4] = 'r'; - memcpy(special_directions+5, close_bracket_position+1, base_len); - special_directions[base_len+7] = '\0'; - printf("%s\n",special_directions); - } - - // let us display items index_lower thru index_higher of this array - s.PutChar('['); - var_success = true; - const char* expr_path = NULL; - const char* ptr_deref_format = "%s[%d]"; - char* ptr_deref_buffer = new char[1024]; - StreamString expr_path_string; - - if(is_pointer) - { - vobj->GetExpressionPath(expr_path_string, true, ValueObject::eHonorPointers); - expr_path = expr_path_string.GetData(); - } - - for(;index_lower<=index_higher;index_lower++) - { - ValueObject* item; - - if(is_array) - item = vobj->GetChildAtIndex(index_lower, true).get(); - else - { -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to deref in phase 0: %s\n",expr_path); -#endif //VERBOSE_FORMATPROMPT_OUTPUT - ::sprintf(ptr_deref_buffer, ptr_deref_format, expr_path, index_lower); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to deref in phase 1: %s\n",ptr_deref_buffer); -#endif //VERBOSE_FORMATPROMPT_OUTPUT - lldb::VariableSP var_sp; - Error error; - item = exe_ctx->frame->GetValueForVariableExpressionPath (ptr_deref_buffer, - eNoDynamicValues, - 0, - var_sp, - error).get(); - if (error.Fail()) - { -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("ERROR: %s\n",error.AsCString("unknown")); -#endif //VERBOSE_FORMATPROMPT_OUTPUT - break; - } - } - - if (!special_directions) - { - targetvalue = item->GetPrintableRepresentation(val_obj_display, custom_format); - if(targetvalue) - s.PutCString(targetvalue); - var_success &= (targetvalue != NULL); - if(custom_format != eFormatInvalid) - item->SetFormat(eFormatDefault); - } - else - { - var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); - } - - if(index_lower < index_higher) - s.PutChar(','); - } - s.PutChar(']'); - break; - - } - else if (is_pointer) - { - var_name_begin++; - uint32_t offset = 0; - DataExtractor read_for_null = vobj->GetDataExtractor(); - if (read_for_null.GetPointer(&offset) == 0) - break; - if (ClangASTContext::IsAggregateType (elem_or_pointee_clang_type) ) - { - Error error; - realvobj = vobj; - vobj = vobj->Dereference(error).get(); - if(!vobj || error.Fail()) - break; - } - else if (ClangASTContext::IsCharType (elem_or_pointee_clang_type)) - { - StreamString sstr; - ExecutionContextScope *exe_scope = vobj->GetExecutionContextScope(); - Process *process = exe_scope->CalculateProcess(); - if(!process) break; - lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; - AddressType cstr_address_type = eAddressTypeInvalid; - DataExtractor data; - size_t bytes_read = 0; - std::vector data_buffer; - Error error; - cstr_address = vobj->GetPointerValue (cstr_address_type, true); - { - const size_t k_max_buf_size = 256; - data_buffer.resize (k_max_buf_size + 1); - // NULL terminate in case we don't get the entire C string - data_buffer.back() = '\0'; - - sstr << '"'; - - data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), k_max_buf_size, error)) > 0) - { - size_t len = strlen(&data_buffer.front()); - if (len == 0) - break; - if (len > bytes_read) - len = bytes_read; - - data.Dump (&sstr, - 0, // Start offset in "data" - eFormatCharArray, // Print as characters - 1, // Size of item (1 byte for a char!) - len, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - - if (len < k_max_buf_size) - break; - cstr_address += k_max_buf_size; - } - sstr << '"'; - s.PutCString(sstr.GetData()); - var_success = true; - break; - } - } - else /*some other pointer type*/ - { - Error error; - realvobj = vobj; - vobj = vobj->Dereference(error).get(); - if(!vobj || error.Fail()) - break; - } - } - else - break; + do_deref_pointer = true; + var_name_begin++; } case 'v': { - const char* targetvalue; ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary; ValueObject* target; lldb::Format custom_format = eFormatInvalid; - int bitfield_lower = -1; - int bitfield_higher = -1; + const char* var_name_final; + const char* var_name_final_if_array_range = NULL; + const char* close_bracket_position; + int64_t index_lower = -1, index_higher = -1; + bool is_array_range = false; if (!vobj) break; // simplest case ${var}, just print vobj's value if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) @@ -1065,217 +985,140 @@ else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) { // this is a variable with some custom format applied to it - const char* var_name_final; + const char* percent_position; target = vobj; val_obj_display = ValueObject::eDisplayValue; - { - const char* percent_position = ::strchr(var_name_begin,'%'); // TODO: make this a constant - //if(!percent_position || percent_position > var_name_end) - // var_name_final = var_name_end; - //else - //{ - var_name_final = percent_position; - char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0'; - memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1); - if ( !FormatManager::GetFormatFromCString(format_name, - true, - custom_format) ) - { - // if this is an @ sign, print ObjC description - if(*format_name == '@') - val_obj_display = ValueObject::eDisplayLanguageSpecific; - } - delete format_name; - //} - } - } - else if (::strncmp(var_name_begin,"var[",strlen("var[")) == 0) - { - // this is a bitfield variable - const char *var_name_final; - target = vobj; - val_obj_display = ValueObject::eDisplayValue; - { - const char* percent_position = ::strchr(var_name_begin,'%'); - if(!percent_position || percent_position > var_name_end) - var_name_final = var_name_end; - else - { - var_name_final = percent_position; - char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0'; - memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1); - if ( !FormatManager::GetFormatFromCString(format_name, - true, - custom_format) ) - { - delete format_name; - break; - } - else - delete format_name; - } - } - - { - // code here might be simpler than in the case below - const char* open_bracket_position = ::strchr(var_name_begin,'['); - if(open_bracket_position && open_bracket_position < var_name_final) - { - const char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield - const char* close_bracket_position = ::strchr(open_bracket_position,']'); - // as usual, we assume that [] will come before % - //printf("trying to expand a []\n"); - var_name_final = open_bracket_position; - if (separator_position == NULL || separator_position > var_name_end) - { - char *end = NULL; - bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0); - bitfield_higher = bitfield_lower; - //printf("got to read low=%d high same\n",bitfield_lower); - } - else if(close_bracket_position && close_bracket_position < var_name_end) - { - char *end = NULL; - bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0); - bitfield_higher = ::strtoul (separator_position+1, &end, 0); - //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher); - } - else - break; - if(bitfield_lower > bitfield_higher) - { - int temp = bitfield_lower; - bitfield_lower = bitfield_higher; - bitfield_higher = temp; - } - } - } + ScanFormatDescriptor(var_name_begin, + var_name_end, + &var_name_final, + &percent_position, + &custom_format, + &val_obj_display); } // this is ${var.something} or multiple .something nested else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) { - // check for custom format string - - // we need this because we might have ${var.something%format}. in this case var_name_end - // still points to the closing }, but we must extract the variable name only up to - // before the %. var_name_final will point to that % sign position - const char* var_name_final; - - { - const char* percent_position = ::strchr(var_name_begin,'%'); - if(!percent_position || percent_position > var_name_end) - var_name_final = var_name_end; - else - { - var_name_final = percent_position; - char* format_name = new char[var_name_end-var_name_final]; format_name[var_name_end-var_name_final-1] = '\0'; - memcpy(format_name, var_name_final+1, var_name_end-var_name_final-1); - if ( !FormatManager::GetFormatFromCString(format_name, - true, - custom_format) ) - { - // if this is an @ sign, print ObjC description - if(*format_name == '@') - val_obj_display = ValueObject::eDisplayLanguageSpecific; - // if this is a V, print the value using the default format - if(*format_name == 'V') - val_obj_display = ValueObject::eDisplayValue; - } - // a good custom format tells us to print the value using it - else - val_obj_display = ValueObject::eDisplayValue; - } - } - - { - const char* open_bracket_position = ::strchr(var_name_begin,'['); - if(open_bracket_position && open_bracket_position < var_name_final) - { - const char* separator_position = ::strchr(open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield - const char* close_bracket_position = ::strchr(open_bracket_position,']'); - // as usual, we assume that [] will come before % - //printf("trying to expand a []\n"); - var_name_final = open_bracket_position; - if (separator_position == NULL || separator_position > var_name_end) - { - char *end = NULL; - bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0); - bitfield_higher = bitfield_lower; - //printf("got to read low=%d high same\n",bitfield_lower); - } - else if(close_bracket_position && close_bracket_position < var_name_end) - { - char *end = NULL; - bitfield_lower = ::strtoul (open_bracket_position+1, &end, 0); - bitfield_higher = ::strtoul (separator_position+1, &end, 0); - //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher); - } - else - break; - if(bitfield_lower > bitfield_higher) - { - int temp = bitfield_lower; - bitfield_lower = bitfield_higher; - bitfield_higher = temp; - } - //*((char*)open_bracket_position) = '\0'; - //printf("variable name is %s\n",var_name_begin); - //*((char*)open_bracket_position) = '['; - } - } + const char* percent_position; + ScanFormatDescriptor(var_name_begin, + var_name_end, + &var_name_final, + &percent_position, + &custom_format, + &val_obj_display); + + const char* open_bracket_position; + const char* separator_position; + ScanBracketedRange(var_name_begin, + var_name_end, + var_name_final, + &open_bracket_position, + &separator_position, + &close_bracket_position, + &var_name_final_if_array_range, + &index_lower, + &index_higher); + Error error; - lldb::VariableSP var_sp; - StreamString sstring; - vobj->GetExpressionPath(sstring, true, ValueObject::eHonorPointers); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to expand in phase 0: %s\n",sstring.GetData()); -#endif //VERBOSE_FORMATPROMPT_OUTPUT - sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to expand in phase 1: %s\n",sstring.GetData()); -#endif //VERBOSE_FORMATPROMPT_OUTPUT - std::string name = std::string(sstring.GetData()); - target = exe_ctx->frame->GetValueForVariableExpressionPath (name.c_str(), - eNoDynamicValues, - 0, - var_sp, - error).get(); - if (error.Fail()) + target = ExpandExpressionPath(vobj, + exe_ctx->frame, + &do_deref_pointer, + var_name_begin, + var_name_final, + error).get(); + + if (error.Fail() || !target) { #ifdef VERBOSE_FORMATPROMPT_OUTPUT printf("ERROR: %s\n",error.AsCString("unknown")); #endif //VERBOSE_FORMATPROMPT_OUTPUT - break; + if (var_name_final_if_array_range) + { + target = ExpandExpressionPath(vobj, + exe_ctx->frame, + &do_deref_pointer, + var_name_begin, + var_name_final_if_array_range, + error).get(); + } + + IFERROR_PRINT_IT + else + is_array_range = true; } + + do_deref_pointer = false; // I have honored the request to deref + } else break; - if (bitfield_lower >= 0) + + if(do_deref_pointer) { - //printf("trying to print a []\n"); - // format this as a bitfield - DataExtractor extractor = target->GetDataExtractor(); - uint32_t item_byte_size = ClangASTType::GetTypeByteSize(target->GetClangAST(), target->GetClangType()); - if(custom_format == eFormatInvalid) - custom_format = eFormatHex; - var_success = - extractor.Dump(&s, 0, custom_format, item_byte_size, 1, 1, LLDB_INVALID_ADDRESS, bitfield_higher-bitfield_lower+1, bitfield_lower) > 0; - //printf("var_success = %s\n",var_success ? "true" : "false"); + // I have not deref-ed yet, let's do it + // this happens when we are not going through GetValueForVariableExpressionPath + // to get to the target ValueObject + Error error; + target = target->Dereference(error).get(); + IFERROR_PRINT_IT + do_deref_pointer = false; } + + if(!is_array_range) + var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); else { - // format this as usual - targetvalue = target->GetPrintableRepresentation(val_obj_display, custom_format); - if(targetvalue) - s.PutCString(targetvalue); - var_success = targetvalue; - //printf("here I come 4 : %s\n",var_success ? "good" : "bad"); - if(custom_format != eFormatInvalid) - target->SetFormat(eFormatDefault); - //printf("here I come 5\n"); + bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType()); + bool is_pointer = ClangASTContext::IsPointerType(vobj->GetClangType()); + + if(!is_array && !is_pointer) + break; + + char* special_directions = NULL; + if (close_bracket_position && (var_name_end-close_bracket_position > 1)) + { + int base_len = var_name_end-close_bracket_position; + special_directions = new char[8+base_len]; + special_directions[0] = '$'; + special_directions[1] = '{'; + special_directions[2] = 'v'; + special_directions[3] = 'a'; + special_directions[4] = 'r'; + memcpy(special_directions+5, close_bracket_position+1, base_len); + special_directions[base_len+7] = '\0'; +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("%s\n",special_directions); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + } + + // let us display items index_lower thru index_higher of this array + s.PutChar('['); + var_success = true; + + if(index_higher < 0) + index_higher = vobj->GetNumChildren() - 1; + + for(;index_lower<=index_higher;index_lower++) + { + Error error; + ValueObject* item = ExpandIndexedExpression(vobj, + index_lower, + exe_ctx->frame, + error).get(); + + + IFERROR_PRINT_IT + if (!special_directions) + var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); + else + var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); + + if(index_lower < index_higher) + s.PutChar(','); + } + s.PutChar(']'); } - break; + break; } case 'a': if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Tue Jul 5 21:13:41 2011 @@ -74,6 +74,7 @@ m_pointers_point_to_load_addrs (false), m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), + m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), m_last_summary_format(), m_last_value_format() @@ -110,6 +111,7 @@ m_pointers_point_to_load_addrs (false), m_is_deref_of_parent (false), m_is_array_item_for_pointer(false), + m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), m_last_summary_format(), m_last_value_format() @@ -515,7 +517,7 @@ s.PutCString(", "); s.PutCString(child_sp.get()->GetName().AsCString()); s.PutChar('='); - s.PutCString(child_sp.get()->GetValueAsCString()); + s.PutCString(child_sp.get()->GetPrintableRepresentation()); } } @@ -768,7 +770,9 @@ if (m_last_value_format) format = m_last_value_format->m_format; else - format = ClangASTType::GetFormat(clang_type); + // force the system into using unsigned integers for bitfields + format = (m_is_bitfield_for_scalar ? eFormatUnsigned : + ClangASTType::GetFormat(clang_type)); } if (ClangASTType::DumpTypeValue (GetClangAST(), // The clang AST @@ -844,15 +848,35 @@ break; } + if (!return_value) + { + // try to pick the other choice + if (val_obj_display == eDisplayValue) + return_value = GetSummaryAsCString(); + else if (val_obj_display == eDisplaySummary) + return_value = GetValueAsCString(); + else + return_value = ""; + } - // try to use the value if the user's choice failed - if(!return_value && val_obj_display != eDisplayValue) - return_value = GetValueAsCString(); - - return return_value; + return (return_value ? return_value : ""); } +bool +ValueObject::DumpPrintableRepresentation(Stream& s, + ValueObjectRepresentationStyle val_obj_display, + lldb::Format custom_format) +{ + const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); + if(targetvalue) + s.PutCString(targetvalue); + bool var_success = (targetvalue != NULL); + if(custom_format != eFormatInvalid) + SetFormat(eFormatDefault); + return var_success; +} + addr_t ValueObject::GetAddressOf (AddressType &address_type, bool scalar_is_load_address) { @@ -1073,6 +1097,12 @@ } bool +ValueObject::IsScalarType () +{ + return ClangASTContext::IsScalarType (GetClangType()); +} + +bool ValueObject::IsIntegerType (bool &is_signed) { return ClangASTContext::IsIntegerType (GetClangType(), is_signed); @@ -1128,6 +1158,47 @@ return synthetic_child_sp; } +ValueObjectSP +ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create) +{ + ValueObjectSP synthetic_child_sp; + if (IsScalarType ()) + { + char index_str[64]; + snprintf(index_str, sizeof(index_str), "[%i-%i]", from, to); + ConstString index_const_str(index_str); + // Check if we have already created a synthetic array member in this + // valid object. If we have we will re-use it. + synthetic_child_sp = GetSyntheticChild (index_const_str); + if (!synthetic_child_sp) + { + ValueObjectChild *synthetic_child; + // We haven't made a synthetic array member for INDEX yet, so + // lets make one and cache it for any future reference. + synthetic_child = new ValueObjectChild(*this, + GetClangAST(), + GetClangType(), + index_const_str, + GetByteSize(), + 0, + to-from+1, + from, + false, + false); + + // Cache the value if we got one back... + if (synthetic_child) + { + AddSyntheticChild(index_const_str, synthetic_child); + synthetic_child_sp = synthetic_child->GetSP(); + synthetic_child_sp->SetName(index_str); + synthetic_child_sp->m_is_bitfield_for_scalar = true; + } + } + } + return synthetic_child_sp; +} + void ValueObject::CalculateDynamicValue (lldb::DynamicValueType use_dynamic) { Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Tue Jul 5 21:13:41 2011 @@ -4464,6 +4464,40 @@ return false; } +bool +ClangASTContext::IsScalarType (lldb::clang_type_t clang_type) +{ + bool is_signed; + if (ClangASTContext::IsIntegerType(clang_type, is_signed)) + return true; + + uint32_t count; + bool is_complex; + return ClangASTContext::IsFloatingPointType(clang_type, count, is_complex) && !is_complex; +} + +bool +ClangASTContext::IsPointerToScalarType (lldb::clang_type_t clang_type) +{ + if (!IsPointerType(clang_type)) + return false; + + QualType qual_type (QualType::getFromOpaquePtr(clang_type)); + lldb::clang_type_t pointee_type = qual_type.getTypePtr()->getPointeeType().getAsOpaquePtr(); + return IsScalarType(pointee_type); +} + +bool +ClangASTContext::IsArrayOfScalarType (lldb::clang_type_t clang_type) +{ + if (!IsArrayType(clang_type)) + return false; + + QualType qual_type (QualType::getFromOpaquePtr(clang_type)); + lldb::clang_type_t item_type = cast(qual_type.getTypePtr())->getElementType().getAsOpaquePtr(); + return IsScalarType(item_type); +} + bool ClangASTContext::GetCXXClassName (clang_type_t clang_type, std::string &class_name) Added: lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp?rev=134458&view=auto ============================================================================== --- lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp (added) +++ lldb/trunk/source/Symbol/TypeHierarchyNavigator.cpp Tue Jul 5 21:13:41 2011 @@ -0,0 +1,121 @@ +//===-- TypeHierarchyNavigator.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/Core/Error.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/TypeHierarchyNavigator.h" + +using namespace lldb; +using namespace lldb_private; + +bool +TypeHierarchyNavigator::LoopThrough(TypeHierarchyNavigatorCallback callback, + void* callback_baton) +{ + return LoopThrough(m_root_type, + callback, + eRootType, + (callback_baton ? callback_baton : m_default_callback_baton)); +} + +bool +TypeHierarchyNavigator::LoopThrough(const clang::QualType& qual_type, + TypeHierarchyNavigatorCallback callback, + RelationshipToCurrentType reason_why_here, + void* callback_baton) +{ + if (qual_type.isNull()) + return true; + clang::QualType type = qual_type.getUnqualifiedType(); + type.removeLocalConst(); type.removeLocalVolatile(); type.removeLocalRestrict(); + const clang::Type* typePtr = type.getTypePtrOrNull(); + if (!typePtr) + return true; + if (!callback(type, reason_why_here, callback_baton)) + return false; + // look for a "base type", whatever that means + if (typePtr->isReferenceType()) + { + if (LoopThrough(type.getNonReferenceType(), callback, eStrippedReference, callback_baton) == false) + return false; + } + if (typePtr->isPointerType()) + { + if (LoopThrough(typePtr->getPointeeType(), callback, eStrippedPointer, callback_baton) == false) + return false; + } + if (typePtr->isObjCObjectPointerType()) + { + /* + for some reason, C++ can quite easily obtain the type hierarchy for a ValueObject + even if the VO represent a pointer-to-class, as long as the typePtr is right + Objective-C on the other hand cannot really complete an @interface when + the VO refers to a pointer-to- at interface + */ + Error error; + ValueObject* target = m_value_object.Dereference(error).get(); + if(error.Fail() || !target) + return true; + if (LoopThrough(typePtr->getPointeeType(), callback, eStrippedPointer, callback_baton) == false) + return false; + } + const clang::ObjCObjectType *objc_class_type = typePtr->getAs(); + if (objc_class_type) + { + clang::ASTContext *ast = m_value_object.GetClangAST(); + if (ClangASTContext::GetCompleteType(ast, m_value_object.GetClangType()) && !objc_class_type->isObjCId()) + { + clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); + if(class_interface_decl) + { + clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); + if(superclass_interface_decl) + { + clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl)); + return LoopThrough(ivar_qual_type, callback, eObjCBaseClass, callback_baton); + } + } + } + } + // for C++ classes, navigate up the hierarchy + if (typePtr->isRecordType()) + { + clang::CXXRecordDecl* record = typePtr->getAsCXXRecordDecl(); + if (record) + { + if (!record->hasDefinition()) + ClangASTContext::GetCompleteType(m_value_object.GetClangAST(), m_value_object.GetClangType()); + if (record->hasDefinition()) + { + clang::CXXRecordDecl::base_class_iterator pos,end; + if( record->getNumBases() > 0) + { + end = record->bases_end(); + for (pos = record->bases_begin(); pos != end; pos++) + if (LoopThrough(pos->getType(), callback, eCXXBaseClass, callback_baton) == false) + return false; + } + if (record->getNumVBases() > 0) + { + end = record->vbases_end(); + for (pos = record->vbases_begin(); pos != end; pos++) + if (LoopThrough(pos->getType(), callback, eCXXVBaseClass, callback_baton) == false) + return false; + } + } + } + } + // try to strip typedef chains + const clang::TypedefType* type_tdef = type->getAs(); + if (type_tdef) + return LoopThrough(type_tdef->getDecl()->getUnderlyingType(), callback, eStrippedTypedef, callback_baton); + else + return true; +} Modified: lldb/trunk/source/Target/StackFrame.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/source/Target/StackFrame.cpp (original) +++ lldb/trunk/source/Target/StackFrame.cpp Tue Jul 5 21:13:41 2011 @@ -645,9 +645,47 @@ { char *end = NULL; long child_index = ::strtol (&var_path[1], &end, 0); - if (end && *end == ']') + if (end && *end == ']' + && *(end-1) != '[') // this code forces an error in the case of arr[]. as bitfield[] is not a good syntax we're good to go { - + if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref) + { + // what we have is *ptr[low]. the most similar C++ syntax is to deref ptr + // and extract bit low out of it. reading array item low + // would be done by saying ptr[low], without a deref * sign + Error error; + ValueObjectSP temp(valobj_sp->Dereference(error)); + if (error.Fail()) + { + valobj_sp->GetExpressionPath (var_expr_path_strm, false); + error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"", + valobj_sp->GetTypeName().AsCString(""), + var_expr_path_strm.GetString().c_str()); + return ValueObjectSP(); + } + valobj_sp = temp; + deref = false; + } + else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref) + { + // what we have is *arr[low]. the most similar C++ syntax is to get arr[0] + // (an operation that is equivalent to deref-ing arr) + // and extract bit low out of it. reading array item low + // would be done by saying arr[low], without a deref * sign + Error error; + ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true)); + if (error.Fail()) + { + valobj_sp->GetExpressionPath (var_expr_path_strm, false); + error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"", + valobj_sp->GetTypeName().AsCString(""), + var_expr_path_strm.GetString().c_str()); + return ValueObjectSP(); + } + valobj_sp = temp; + deref = false; + } + if (valobj_sp->IsPointerType ()) { child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true); @@ -674,6 +712,19 @@ var_expr_path_strm.GetString().c_str()); } } + else if (ClangASTContext::IsScalarType(valobj_sp->GetClangType())) + { + // this is a bitfield asking to display just one bit + child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, child_index, true); + if (!child_valobj_sp) + { + valobj_sp->GetExpressionPath (var_expr_path_strm, false); + error.SetErrorStringWithFormat ("bitfield range %i-%i is not valid for \"(%s) %s\"", + child_index, child_index, + valobj_sp->GetTypeName().AsCString(""), + var_expr_path_strm.GetString().c_str()); + } + } else { valobj_sp->GetExpressionPath (var_expr_path_strm, false); @@ -702,6 +753,97 @@ // able to find the child member break; } + else if(end && *end == '-') + { + // this is most probably a BitField, let's take a look + char *real_end = NULL; + long final_index = ::strtol (end+1, &real_end, 0); + if(real_end && *real_end == ']') + { + // if the format given is [high-low], swap range + if(child_index > final_index) + { + long temp = child_index; + child_index = final_index; + final_index = temp; + } + + if (ClangASTContext::IsPointerToScalarType(valobj_sp->GetClangType()) && deref) + { + // what we have is *ptr[low-high]. the most similar C++ syntax is to deref ptr + // and extract bits low thru high out of it. reading array items low thru high + // would be done by saying ptr[low-high], without a deref * sign + Error error; + ValueObjectSP temp(valobj_sp->Dereference(error)); + if (error.Fail()) + { + valobj_sp->GetExpressionPath (var_expr_path_strm, false); + error.SetErrorStringWithFormat ("could not dereference \"(%s) %s\"", + valobj_sp->GetTypeName().AsCString(""), + var_expr_path_strm.GetString().c_str()); + return ValueObjectSP(); + } + valobj_sp = temp; + deref = false; + } + else if (ClangASTContext::IsArrayOfScalarType(valobj_sp->GetClangType()) && deref) + { + // what we have is *arr[low-high]. the most similar C++ syntax is to get arr[0] + // (an operation that is equivalent to deref-ing arr) + // and extract bits low thru high out of it. reading array items low thru high + // would be done by saying arr[low-high], without a deref * sign + Error error; + ValueObjectSP temp(valobj_sp->GetChildAtIndex (0, true)); + if (error.Fail()) + { + valobj_sp->GetExpressionPath (var_expr_path_strm, false); + error.SetErrorStringWithFormat ("could not get item 0 for \"(%s) %s\"", + valobj_sp->GetTypeName().AsCString(""), + var_expr_path_strm.GetString().c_str()); + return ValueObjectSP(); + } + valobj_sp = temp; + deref = false; + } + + child_valobj_sp = valobj_sp->GetSyntheticBitFieldChild(child_index, final_index, true); + if (!child_valobj_sp) + { + valobj_sp->GetExpressionPath (var_expr_path_strm, false); + error.SetErrorStringWithFormat ("bitfield range %i-%i is not valid for \"(%s) %s\"", + child_index, final_index, + valobj_sp->GetTypeName().AsCString(""), + var_expr_path_strm.GetString().c_str()); + } + } + + if (!child_valobj_sp) + { + // Invalid bitfield range... + return ValueObjectSP(); + } + + // Erase the bitfield member specification '[%i-%i]' where + // %i is the index + var_path.erase(0, (real_end - var_path.c_str()) + 1); + separator_idx = var_path.find_first_of(".-["); + if (use_dynamic != lldb::eNoDynamicValues) + { + ValueObjectSP dynamic_value_sp(child_valobj_sp->GetDynamicValue(use_dynamic)); + if (dynamic_value_sp) + child_valobj_sp = dynamic_value_sp; + } + // Break out early from the switch since we were + // able to find the child member + break; + + } + } + else + { + error.SetErrorStringWithFormat("invalid square bracket encountered after \"%s\" in \"%s\"", + var_expr_path_strm.GetString().c_str(), + var_path.c_str()); } return ValueObjectSP(); Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py Tue Jul 5 21:13:41 2011 @@ -53,13 +53,6 @@ # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) - self.runCmd("type summary add -f \"pippo\" -x \"IUseCharStar\"") - - self.expect("frame variable iEncapsulateCharStar", - substrs = ['pippo']) - - self.runCmd("type summary clear") - self.runCmd("type summary add -f \"pippo\" \"i_am_cool\"") self.runCmd("type summary add -f \"pluto\" -x \"i_am_cool[a-z]*\"") @@ -77,12 +70,12 @@ self.runCmd("type summary clear") - self.runCmd("type summary add -f \"${*var[]}\" -x \"int \\[[0-9]\\]") + self.runCmd("type summary add -f \"${var[]}\" -x \"int \\[[0-9]\\]") self.expect("frame variable int_array", substrs = ['1,2,3,4,5']) - self.runCmd("type summary add -f \"${*var[].integer}\" -x \"i_am_cool \\[[0-9]\\]") + self.runCmd("type summary add -f \"${var[].integer}\" -x \"i_am_cool \\[[0-9]\\]") self.expect("frame variable cool_array", substrs = ['1,1,1,1,6']) @@ -93,17 +86,79 @@ self.expect("frame variable iAmInt", substrs = ['01']) - - self.runCmd("type summary add -f \"${*var[0-1]%x}\" \"int\"") - - self.expect("frame variable iAmInt", matching=False, - substrs = ['01']) - + self.runCmd("type summary add -f \"${var[0-1]%x}\" \"int\"") self.expect("frame variable iAmInt", substrs = ['01']) + self.runCmd("type summary clear") + + self.runCmd("type summary add -f \"${var[0-1]%x}\" int") + self.runCmd("type summary add -f \"${var[0-31]%x}\" float") + + self.expect("frame variable *pointer", + substrs = ['0x', + '2']) + + self.expect("frame variable cool_array[3].floating", + substrs = ['0x']) + + self.runCmd("type summary add -f \"low bits are ${*var[0-1]} tgt is ${*var}\" \"int *\"") + + self.expect("frame variable pointer", + substrs = ['low bits are', + 'tgt is 6']) + + self.runCmd("type summary add -f \"${*var[0-1]}\" -x \"int \[[0-9]\]\"") + + self.expect("frame variable int_array", + substrs = ['3']) + + self.runCmd("type summary clear") + + self.runCmd("type summary add -f \"${var[0-1]}\" -x \"int \[[0-9]\]\"") + + self.expect("frame variable int_array", + substrs = ['1,2']) + + self.runCmd("type summary clear") + + self.runCmd("type summary add -c -x \"i_am_cool \[[0-9]\]\"") + self.runCmd("type summary add -c i_am_cool") + + self.expect("frame variable cool_array", + substrs = ['[0]', + '[1]', + '[2]', + '[3]', + '[4]', + 'integer', + 'character', + 'floating']) + + self.runCmd("type summary add -f \"int = ${*var.int_pointer}, float = ${*var.float_pointer}\" IWrapPointers") + + self.expect("frame variable wrapper", + substrs = ['int = 4', + 'float = 1.1']) + + self.runCmd("type summary add -f \"low bits = ${*var.int_pointer[2]}\" IWrapPointers -p") + + self.expect("frame variable wrapper", + substrs = ['low bits = 1']) + + self.expect("frame variable *wrap_pointer", + substrs = ['low bits = 1']) + + self.runCmd("type summary clear") + + self.runCmd("type summary add -f \"${var[0][0-2]%hex}\" -x \"int \[[0-9]\]\"") + + self.expect("frame variable int_array", + substrs = ['0x', + '7']) + if __name__ == '__main__': import atexit Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp Tue Jul 5 21:13:41 2011 @@ -34,10 +34,11 @@ floating((F1 + F2)/2) {} }; -struct IUseCharStar +struct IWrapPointers { - const char* pointer; - IUseCharStar() : pointer("Hello world") {} + int* int_pointer; + float* float_pointer; + IWrapPointers() : int_pointer(new int(4)), float_pointer(new float(1.111)) {} }; int main (int argc, const char * argv[]) @@ -58,7 +59,13 @@ int int_array[] = {1,2,3,4,5}; - IUseCharStar iEncapsulateCharStar; + IWrapPointers wrapper; + + *int_array = -1; + + int* pointer = &cool_array[4].integer; + + IWrapPointers *wrap_pointer = &wrapper; return 0; // Set break point at this line. } \ No newline at end of file Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py?rev=134458&r1=134457&r2=134458&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Tue Jul 5 21:13:41 2011 @@ -129,7 +129,7 @@ substrs = ['a test'], matching = False) - self.runCmd("type summary add -f \"${*var[1-3]}\" \"int [5]\"") + self.runCmd("type summary add -f \"${var[1-3]}\" \"int [5]\"") self.expect("frame variable int_array", substrs = ['2', @@ -138,8 +138,8 @@ self.runCmd("type summary clear") - self.runCmd("type summary add -f \"${*var[0-2].integer}\" \"i_am_cool *\"") - self.runCmd("type summary add -f \"${*var[2-4].integer}\" \"i_am_cool [5]\"") + self.runCmd("type summary add -f \"${var[0-2].integer}\" \"i_am_cool *\"") + self.runCmd("type summary add -f \"${var[2-4].integer}\" \"i_am_cool [5]\"") self.expect("frame variable cool_array", substrs = ['1,1,6']) From gclayton at apple.com Tue Jul 5 23:07:21 2011 From: gclayton at apple.com (Greg Clayton) Date: Wed, 06 Jul 2011 04:07:21 -0000 Subject: [Lldb-commits] [lldb] r134461 - in /lldb/trunk: include/lldb/Core/RegisterValue.h include/lldb/Target/StackFrame.h source/API/SBFrame.cpp source/Core/Debugger.cpp source/Core/Disassembler.cpp source/Core/RegisterValue.cpp source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp source/Plugins/Instruction/ARM/EmulateInstructionARM.h source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h source/Target/StackFrame.cpp source/Target/UnixSignals.cpp Message-ID: <20110706040721.EBF2E2A6C12C@llvm.org> Author: gclayton Date: Tue Jul 5 23:07:21 2011 New Revision: 134461 URL: http://llvm.org/viewvc/llvm-project?rev=134461&view=rev Log: Fixed some issues with ARM backtraces by not processing any push/pop instructions if they are conditional. Also fixed issues where the PC wasn't getting bit zero stripped for ARM targets when a stack frame was thumb. We now properly call through the GetOpcodeLoadAddress() functions to make sure the addresses are properly stripped for any targets that may decorate up their addresses. We now don't pass the SIGSTOP signals along. We can revisit this soon, but currently this was interfering with debugging some older ARM targets that don't have vCont support in the GDB server. Modified: lldb/trunk/include/lldb/Core/RegisterValue.h lldb/trunk/include/lldb/Target/StackFrame.h lldb/trunk/source/API/SBFrame.cpp lldb/trunk/source/Core/Debugger.cpp lldb/trunk/source/Core/Disassembler.cpp lldb/trunk/source/Core/RegisterValue.cpp lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h lldb/trunk/source/Target/StackFrame.cpp lldb/trunk/source/Target/UnixSignals.cpp Modified: lldb/trunk/include/lldb/Core/RegisterValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/RegisterValue.h?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/RegisterValue.h (original) +++ lldb/trunk/include/lldb/Core/RegisterValue.h Tue Jul 5 23:07:21 2011 @@ -204,6 +204,12 @@ } bool + ClearBit (uint32_t bit); + + bool + SetBit (uint32_t bit); + + bool operator == (const RegisterValue &rhs) const; bool Modified: lldb/trunk/include/lldb/Target/StackFrame.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/StackFrame.h?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/StackFrame.h (original) +++ lldb/trunk/include/lldb/Target/StackFrame.h Tue Jul 5 23:07:21 2011 @@ -74,7 +74,7 @@ StackID& GetStackID(); - Address& + const Address& GetFrameCodeAddress(); void Modified: lldb/trunk/source/API/SBFrame.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBFrame.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/API/SBFrame.cpp (original) +++ lldb/trunk/source/API/SBFrame.cpp Tue Jul 5 23:07:21 2011 @@ -258,7 +258,7 @@ if (m_opaque_sp) { Mutex::Locker api_locker (m_opaque_sp->GetThread().GetProcess().GetTarget().GetAPIMutex()); - addr = m_opaque_sp->GetFrameCodeAddress().GetLoadAddress (&m_opaque_sp->GetThread().GetProcess().GetTarget()); + addr = m_opaque_sp->GetFrameCodeAddress().GetOpcodeLoadAddress (&m_opaque_sp->GetThread().GetProcess().GetTarget()); } LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Tue Jul 5 23:07:21 2011 @@ -715,7 +715,7 @@ ValueObject::ValueObjectRepresentationStyle* val_obj_display) { *percent_position = ::strchr(var_name_begin,'%'); - if(!*percent_position || *percent_position > var_name_end) + if (!*percent_position || *percent_position > var_name_end) *var_name_final = var_name_end; else { @@ -727,10 +727,10 @@ *custom_format) ) { // if this is an @ sign, print ObjC description - if(*format_name == '@') + if (*format_name == '@') *val_obj_display = ValueObject::eDisplayLanguageSpecific; // if this is a V, print the value using the default format - if(*format_name == 'V') + if (*format_name == 'V') *val_obj_display = ValueObject::eDisplayValue; } // a good custom format tells us to print the value using it @@ -753,14 +753,14 @@ int64_t* index_higher) { *open_bracket_position = ::strchr(var_name_begin,'['); - if(*open_bracket_position && *open_bracket_position < var_name_final) + if (*open_bracket_position && *open_bracket_position < var_name_final) { *separator_position = ::strchr(*open_bracket_position,'-'); // might be NULL if this is a simple var[N] bitfield *close_bracket_position = ::strchr(*open_bracket_position,']'); // as usual, we assume that [] will come before % //printf("trying to expand a []\n"); *var_name_final_if_array_range = *open_bracket_position; - if(*close_bracket_position - *open_bracket_position == 1) + if (*close_bracket_position - *open_bracket_position == 1) { *index_lower = 0; } @@ -771,7 +771,7 @@ *index_higher = *index_lower; //printf("got to read low=%d high same\n",bitfield_lower); } - else if(*close_bracket_position && *close_bracket_position < var_name_end) + else if (*close_bracket_position && *close_bracket_position < var_name_end) { char *end = NULL; *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); @@ -803,9 +803,9 @@ StreamString sstring; VariableSP var_sp; - if(*do_deref_pointer) + if (*do_deref_pointer) sstring.PutChar('*'); - else if(vobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(vobj->GetParent()->GetClangType()) && !vobj->IsArrayItemForPointer()) + else if (vobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(vobj->GetParent()->GetClangType()) && !vobj->IsArrayItemForPointer()) { sstring.PutChar('*'); *do_deref_pointer = true; @@ -837,7 +837,7 @@ ValueObjectSP item; bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType()); - if(is_array) + if (is_array) return vobj->GetChildAtIndex(index, true); else { @@ -881,7 +881,7 @@ const char *p; for (p = format; *p != '\0'; ++p) { - if(realvobj) + if (realvobj) { vobj = realvobj; realvobj = NULL; @@ -961,165 +961,169 @@ { case '*': { - if (!vobj) break; + if (!vobj) + break; do_deref_pointer = true; var_name_begin++; } + // Fall through... + case 'v': { - ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary; - ValueObject* target; - lldb::Format custom_format = eFormatInvalid; - const char* var_name_final; - const char* var_name_final_if_array_range = NULL; - const char* close_bracket_position; - int64_t index_lower = -1, index_higher = -1; - bool is_array_range = false; - if (!vobj) break; - // simplest case ${var}, just print vobj's value - if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) - { - target = vobj; - val_obj_display = ValueObject::eDisplayValue; - } - else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) - { - // this is a variable with some custom format applied to it - const char* percent_position; - target = vobj; - val_obj_display = ValueObject::eDisplayValue; - ScanFormatDescriptor(var_name_begin, - var_name_end, - &var_name_final, - &percent_position, - &custom_format, - &val_obj_display); - } - // this is ${var.something} or multiple .something nested - else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) - { + ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary; + ValueObject* target = NULL; + lldb::Format custom_format = eFormatInvalid; + const char* var_name_final = NULL; + const char* var_name_final_if_array_range = NULL; + const char* close_bracket_position = NULL; + int64_t index_lower = -1; + int64_t index_higher = -1; + bool is_array_range = false; + if (!vobj) break; + // simplest case ${var}, just print vobj's value + if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) + { + target = vobj; + val_obj_display = ValueObject::eDisplayValue; + } + else if (::strncmp(var_name_begin,"var%",strlen("var%")) == 0) + { + // this is a variable with some custom format applied to it + const char* percent_position; + target = vobj; + val_obj_display = ValueObject::eDisplayValue; + ScanFormatDescriptor (var_name_begin, + var_name_end, + &var_name_final, + &percent_position, + &custom_format, + &val_obj_display); + } + // this is ${var.something} or multiple .something nested + else if (::strncmp (var_name_begin, "var", strlen("var")) == 0) + { - const char* percent_position; - ScanFormatDescriptor(var_name_begin, - var_name_end, - &var_name_final, - &percent_position, - &custom_format, - &val_obj_display); - - const char* open_bracket_position; - const char* separator_position; - ScanBracketedRange(var_name_begin, - var_name_end, - var_name_final, - &open_bracket_position, - &separator_position, - &close_bracket_position, - &var_name_final_if_array_range, - &index_lower, - &index_higher); - - Error error; - target = ExpandExpressionPath(vobj, - exe_ctx->frame, - &do_deref_pointer, - var_name_begin, - var_name_final, - error).get(); + const char* percent_position; + ScanFormatDescriptor (var_name_begin, + var_name_end, + &var_name_final, + &percent_position, + &custom_format, + &val_obj_display); + + const char* open_bracket_position; + const char* separator_position; + ScanBracketedRange (var_name_begin, + var_name_end, + var_name_final, + &open_bracket_position, + &separator_position, + &close_bracket_position, + &var_name_final_if_array_range, + &index_lower, + &index_higher); + + Error error; + target = ExpandExpressionPath (vobj, + exe_ctx->frame, + &do_deref_pointer, + var_name_begin, + var_name_final, + error).get(); - if (error.Fail() || !target) - { + if (error.Fail() || !target) + { #ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("ERROR: %s\n",error.AsCString("unknown")); + printf("ERROR: %s\n",error.AsCString("unknown")); #endif //VERBOSE_FORMATPROMPT_OUTPUT - if (var_name_final_if_array_range) - { - target = ExpandExpressionPath(vobj, - exe_ctx->frame, - &do_deref_pointer, - var_name_begin, - var_name_final_if_array_range, - error).get(); + if (var_name_final_if_array_range) + { + target = ExpandExpressionPath(vobj, + exe_ctx->frame, + &do_deref_pointer, + var_name_begin, + var_name_final_if_array_range, + error).get(); + } + + IFERROR_PRINT_IT + else + is_array_range = true; } - IFERROR_PRINT_IT - else - is_array_range = true; - } - - do_deref_pointer = false; // I have honored the request to deref + do_deref_pointer = false; // I have honored the request to deref - } - else - break; - - if(do_deref_pointer) - { - // I have not deref-ed yet, let's do it - // this happens when we are not going through GetValueForVariableExpressionPath - // to get to the target ValueObject - Error error; - target = target->Dereference(error).get(); - IFERROR_PRINT_IT - do_deref_pointer = false; - } - - if(!is_array_range) - var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); - else - { - bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType()); - bool is_pointer = ClangASTContext::IsPointerType(vobj->GetClangType()); - - if(!is_array && !is_pointer) + } + else break; - - char* special_directions = NULL; - if (close_bracket_position && (var_name_end-close_bracket_position > 1)) + + if (do_deref_pointer) { - int base_len = var_name_end-close_bracket_position; - special_directions = new char[8+base_len]; - special_directions[0] = '$'; - special_directions[1] = '{'; - special_directions[2] = 'v'; - special_directions[3] = 'a'; - special_directions[4] = 'r'; - memcpy(special_directions+5, close_bracket_position+1, base_len); - special_directions[base_len+7] = '\0'; -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("%s\n",special_directions); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + // I have not deref-ed yet, let's do it + // this happens when we are not going through GetValueForVariableExpressionPath + // to get to the target ValueObject + Error error; + target = target->Dereference(error).get(); + IFERROR_PRINT_IT + do_deref_pointer = false; } - - // let us display items index_lower thru index_higher of this array - s.PutChar('['); - var_success = true; - - if(index_higher < 0) - index_higher = vobj->GetNumChildren() - 1; - - for(;index_lower<=index_higher;index_lower++) + + if (!is_array_range) + var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); + else { - Error error; - ValueObject* item = ExpandIndexedExpression(vobj, - index_lower, - exe_ctx->frame, - error).get(); - + bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType()); + bool is_pointer = ClangASTContext::IsPointerType(vobj->GetClangType()); - IFERROR_PRINT_IT - if (!special_directions) - var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); - else - var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); + if (!is_array && !is_pointer) + break; - if(index_lower < index_higher) - s.PutChar(','); + char* special_directions = NULL; + if (close_bracket_position && (var_name_end-close_bracket_position > 1)) + { + int base_len = var_name_end-close_bracket_position; + special_directions = new char[8+base_len]; + special_directions[0] = '$'; + special_directions[1] = '{'; + special_directions[2] = 'v'; + special_directions[3] = 'a'; + special_directions[4] = 'r'; + memcpy(special_directions+5, close_bracket_position+1, base_len); + special_directions[base_len+7] = '\0'; +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("%s\n",special_directions); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + } + + // let us display items index_lower thru index_higher of this array + s.PutChar('['); + var_success = true; + + if (index_higher < 0) + index_higher = vobj->GetNumChildren() - 1; + + for (;index_lower<=index_higher;index_lower++) + { + Error error; + ValueObject* item = ExpandIndexedExpression(vobj, + index_lower, + exe_ctx->frame, + error).get(); + + + IFERROR_PRINT_IT + if (!special_directions) + var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); + else + var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item); + + if (index_lower < index_higher) + s.PutChar(','); + } + s.PutChar(']'); } - s.PutChar(']'); } break; - } case 'a': if (::strncmp (var_name_begin, "addr}", strlen("addr}")) == 0) { Modified: lldb/trunk/source/Core/Disassembler.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Disassembler.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Core/Disassembler.cpp (original) +++ lldb/trunk/source/Core/Disassembler.cpp Tue Jul 5 23:07:21 2011 @@ -331,7 +331,7 @@ SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; - Address *pc_addr_ptr = NULL; + const Address *pc_addr_ptr = NULL; ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope(); if (exe_ctx.frame) pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress(); Modified: lldb/trunk/source/Core/RegisterValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/RegisterValue.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Core/RegisterValue.cpp (original) +++ lldb/trunk/source/Core/RegisterValue.cpp Tue Jul 5 23:07:21 2011 @@ -1000,3 +1000,150 @@ return true; } +bool +RegisterValue::ClearBit (uint32_t bit) +{ + switch (m_type) + { + case eTypeInvalid: + break; + + case eTypeUInt8: + if (bit < 8) + { + m_data.uint8 &= ~(1u << bit); + return true; + } + break; + + case eTypeUInt16: + if (bit < 16) + { + m_data.uint16 &= ~(1u << bit); + return true; + } + break; + + case eTypeUInt32: + if (bit < 32) + { + m_data.uint32 &= ~(1u << bit); + return true; + } + break; + + case eTypeUInt64: + if (bit < 64) + { + m_data.uint64 &= ~(1ull << (uint64_t)bit); + return true; + } + break; +#if defined (ENABLE_128_BIT_SUPPORT) + case eTypeUInt128: + if (bit < 64) + { + m_data.uint128 &= ~((__uint128_t)1ull << (__uint128_t)bit); + return true; + } +#endif + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + break; + + case eTypeBytes: + if (m_data.buffer.byte_order == eByteOrderBig || m_data.buffer.byte_order == eByteOrderLittle) + { + uint32_t byte_idx; + if (m_data.buffer.byte_order == eByteOrderBig) + byte_idx = m_data.buffer.length - (bit / 8) - 1; + else + byte_idx = bit / 8; + + const uint32_t byte_bit = bit % 8; + if (byte_idx < m_data.buffer.length) + { + m_data.buffer.bytes[byte_idx] &= ~(1u << byte_bit); + return true; + } + } + break; + } + return false; +} + + +bool +RegisterValue::SetBit (uint32_t bit) +{ + switch (m_type) + { + case eTypeInvalid: + break; + + case eTypeUInt8: + if (bit < 8) + { + m_data.uint8 |= (1u << bit); + return true; + } + break; + + case eTypeUInt16: + if (bit < 16) + { + m_data.uint16 |= (1u << bit); + return true; + } + break; + + case eTypeUInt32: + if (bit < 32) + { + m_data.uint32 |= (1u << bit); + return true; + } + break; + + case eTypeUInt64: + if (bit < 64) + { + m_data.uint64 |= (1ull << (uint64_t)bit); + return true; + } + break; +#if defined (ENABLE_128_BIT_SUPPORT) + case eTypeUInt128: + if (bit < 64) + { + m_data.uint128 |= ((__uint128_t)1ull << (__uint128_t)bit); + return true; + } +#endif + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + break; + + case eTypeBytes: + if (m_data.buffer.byte_order == eByteOrderBig || m_data.buffer.byte_order == eByteOrderLittle) + { + uint32_t byte_idx; + if (m_data.buffer.byte_order == eByteOrderBig) + byte_idx = m_data.buffer.length - (bit / 8) - 1; + else + byte_idx = bit / 8; + + const uint32_t byte_bit = bit % 8; + if (byte_idx < m_data.buffer.length) + { + m_data.buffer.bytes[byte_idx] |= (1u << byte_bit); + return true; + } + } + break; + } + return false; +} + Modified: lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp (original) +++ lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp Tue Jul 5 23:07:21 2011 @@ -327,8 +327,9 @@ } #endif + bool conditional = false; bool success = false; - if (ConditionPassed(opcode)) + if (ConditionPassed(opcode, &conditional)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -381,7 +382,10 @@ uint32_t i; EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPushRegisterOnStack; + if (conditional) + context.type = EmulateInstruction::eContextRegisterStore; + else + context.type = EmulateInstruction::eContextPushRegisterOnStack; RegisterInfo reg_info; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -447,7 +451,9 @@ bool success = false; - if (ConditionPassed(opcode)) { + bool conditional = false; + if (ConditionPassed(opcode, &conditional)) + { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); if (!success) @@ -508,7 +514,10 @@ uint32_t i, data; EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPopRegisterOffStack; + if (conditional) + context.type = EmulateInstruction::eContextRegisterLoad; + else + context.type = EmulateInstruction::eContextPopRegisterOffStack; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -1847,9 +1856,9 @@ } #endif + bool conditional = false; bool success = false; - - if (ConditionPassed(opcode)) + if (ConditionPassed(opcode, &conditional)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -1894,7 +1903,10 @@ addr = sp; EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPushRegisterOnStack; + if (conditional) + context.type = EmulateInstruction::eContextRegisterStore; + else + context.type = EmulateInstruction::eContextPushRegisterOnStack; RegisterInfo sp_reg; RegisterInfo dwarf_reg; @@ -1955,8 +1967,8 @@ #endif bool success = false; - - if (ConditionPassed(opcode)) + bool conditional = false; + if (ConditionPassed(opcode, &conditional)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -1998,7 +2010,10 @@ uint32_t i; EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPushRegisterOnStack; + if (conditional) + context.type = EmulateInstruction::eContextRegisterStore; + else + context.type = EmulateInstruction::eContextPushRegisterOnStack; RegisterInfo dwarf_reg; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -2048,8 +2063,8 @@ #endif bool success = false; - - if (ConditionPassed(opcode)) + bool conditional = false; + if (ConditionPassed(opcode, &conditional)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2092,7 +2107,10 @@ uint64_t data; // uint64_t to accomodate 64-bit registers. EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPopRegisterOffStack; + if (conditional) + context.type = EmulateInstruction::eContextRegisterLoad; + else + context.type = EmulateInstruction::eContextPopRegisterOffStack; RegisterInfo dwarf_reg; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -3303,8 +3321,8 @@ #endif bool success = false; - - if (ConditionPassed(opcode)) + bool conditional = false; + if (ConditionPassed(opcode, &conditional)) { uint32_t n; uint32_t registers = 0; @@ -3376,7 +3394,12 @@ context.type = EmulateInstruction::eContextRegisterPlusOffset; context.SetRegisterPlusOffset (dwarf_reg, offset); if (wback && (n == 13)) // Pop Instruction - context.type = EmulateInstruction::eContextPopRegisterOffStack; + { + if (conditional) + context.type = EmulateInstruction::eContextRegisterLoad; + else + context.type = EmulateInstruction::eContextPopRegisterOffStack; + } // R[i] = MemA [address, 4]; address = address + 4; uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); @@ -12849,7 +12872,7 @@ } bool -EmulateInstructionARM::ConditionPassed (const uint32_t opcode) +EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional) { // If we are ignoring conditions, then always return true. // this allows us to iterate over disassembly code and still @@ -12857,6 +12880,9 @@ // bits set in the CPSR register... if (m_ignore_conditions) return true; + + if (is_conditional) + *is_conditional = true; const uint32_t cond = CurrentCond (opcode); @@ -12868,33 +12894,38 @@ { case 0: if (m_opcode_cpsr == 0) - return true; - result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; break; case 1: - if (m_opcode_cpsr == 0) - return true; - result = (m_opcode_cpsr & MASK_CPSR_C) != 0; + if (m_opcode_cpsr == 0) + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_C) != 0; break; case 2: - if (m_opcode_cpsr == 0) - return true; - result = (m_opcode_cpsr & MASK_CPSR_N) != 0; + if (m_opcode_cpsr == 0) + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_N) != 0; break; case 3: - if (m_opcode_cpsr == 0) - return true; - result = (m_opcode_cpsr & MASK_CPSR_V) != 0; + if (m_opcode_cpsr == 0) + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_V) != 0; break; case 4: - if (m_opcode_cpsr == 0) - return true; - result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); + if (m_opcode_cpsr == 0) + result = true; + else + result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); break; case 5: - if (m_opcode_cpsr == 0) - return true; - else + if (m_opcode_cpsr == 0) + result = true; + else { bool n = (m_opcode_cpsr & MASK_CPSR_N); bool v = (m_opcode_cpsr & MASK_CPSR_V); @@ -12902,9 +12933,9 @@ } break; case 6: - if (m_opcode_cpsr == 0) - return true; - else + if (m_opcode_cpsr == 0) + result = true; + else { bool n = (m_opcode_cpsr & MASK_CPSR_N); bool v = (m_opcode_cpsr & MASK_CPSR_V); @@ -12912,6 +12943,10 @@ } break; case 7: + // Always execute (cond == 0b1110, or the special 0b1111 which gives + // opcodes different meanings, but always means execution happpens. + if (is_conditional) + *is_conditional = false; result = true; break; } Modified: lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h (original) +++ lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.h Tue Jul 5 23:07:21 2011 @@ -189,7 +189,9 @@ ArchVersion(); bool - ConditionPassed (const uint32_t opcode); + ConditionPassed (const uint32_t opcode, + bool *is_conditional = NULL); // Filled in with true if the opcode is a conditional opcode + // Filled in with false if the opcode is always executed uint32_t CurrentCond (const uint32_t opcode); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp Tue Jul 5 23:07:21 2011 @@ -119,7 +119,7 @@ GDBRemoteRegisterContext::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) { // Read the register - if (ReadRegisterBytes (reg_info, value, m_reg_data)) + if (ReadRegisterBytes (reg_info, m_reg_data)) { const bool partial_data_ok = false; Error error (value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok)); @@ -156,7 +156,7 @@ bool -GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, RegisterValue &value, DataExtractor &data) +GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data) { GDBRemoteCommunicationClient &gdb_comm (GetGDBProcess().GetGDBRemote()); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h Tue Jul 5 23:07:21 2011 @@ -227,7 +227,6 @@ bool ReadRegisterBytes (const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue &value, lldb_private::DataExtractor &data); bool Modified: lldb/trunk/source/Target/StackFrame.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StackFrame.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Target/StackFrame.cpp (original) +++ lldb/trunk/source/Target/StackFrame.cpp Tue Jul 5 23:07:21 2011 @@ -209,7 +209,7 @@ m_id.SetSymbolContextScope (symbol_scope); } -Address& +const Address& StackFrame::GetFrameCodeAddress() { if (m_flags.IsClear(RESOLVED_FRAME_CODE_ADDR) && !m_frame_code_addr.IsSectionOffset()) @@ -218,10 +218,9 @@ // Resolve the PC into a temporary address because if ResolveLoadAddress // fails to resolve the address, it will clear the address object... - Address resolved_pc; - if (m_thread.GetProcess().GetTarget().GetSectionLoadList().ResolveLoadAddress(m_frame_code_addr.GetOffset(), resolved_pc)) + + if (m_frame_code_addr.SetOpcodeLoadAddress (m_frame_code_addr.GetOffset(), &m_thread.GetProcess().GetTarget())) { - m_frame_code_addr = resolved_pc; const Section *section = m_frame_code_addr.GetSection(); if (section) { Modified: lldb/trunk/source/Target/UnixSignals.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/UnixSignals.cpp?rev=134461&r1=134460&r2=134461&view=diff ============================================================================== --- lldb/trunk/source/Target/UnixSignals.cpp (original) +++ lldb/trunk/source/Target/UnixSignals.cpp Tue Jul 5 23:07:21 2011 @@ -59,39 +59,39 @@ // order, you can either subclass this class, and use Add & Remove to change them // or you can subclass and build them afresh in your constructor; m_signals.clear(); - // SIGNO NAME SHORT NAME SUPPRESS STOP NOTIFY DESCRIPTION - // ====== ============ ========== ========= ====== ====== =================================================== - AddSignal (1, "SIGHUP", "HUP", false, true, true, "hangup"); - AddSignal (2, "SIGINT", "INT", true, true, true, "interrupt"); - AddSignal (3, "SIGQUIT", "QUIT", false, true, true, "quit"); - AddSignal (4, "SIGILL", "ILL", false, true, true, "illegal instruction"); - AddSignal (5, "SIGTRAP", "TRAP", true, true, true, "trace trap (not reset when caught)"); - AddSignal (6, "SIGABRT", "ABRT", false, true, true, "abort()"); - AddSignal (7, "SIGEMT", "EMT", false, true, true, "pollable event"); - AddSignal (8, "SIGFPE", "FPE", false, true, true, "floating point exception"); - AddSignal (9, "SIGKILL", "KILL", false, true, true, "kill"); - AddSignal (10, "SIGBUS", "BUS", false, true, true, "bus error"); - AddSignal (11, "SIGSEGV", "SEGV", false, true, true, "segmentation violation"); - AddSignal (12, "SIGSYS", "SYS", false, true, true, "bad argument to system call"); - AddSignal (13, "SIGPIPE", "PIPE", false, true, true, "write on a pipe with no one to read it"); - AddSignal (14, "SIGALRM", "ALRM", false, false, true, "alarm clock"); - AddSignal (15, "SIGTERM", "TERM", false, true, true, "software termination signal from kill"); - AddSignal (16, "SIGURG", "URG", false, false, false, "urgent condition on IO channel"); - AddSignal (17, "SIGSTOP", "STOP", false, true, true, "sendable stop signal not from tty"); - AddSignal (18, "SIGTSTP", "TSTP", false, true, true, "stop signal from tty"); - AddSignal (19, "SIGCONT", "CONT", false, true, true, "continue a stopped process"); - AddSignal (20, "SIGCHLD", "CHLD", false, false, true, "to parent on child stop or exit"); - AddSignal (21, "SIGTTIN", "TTIN", false, true, true, "to readers process group upon background tty read"); - AddSignal (22, "SIGTTOU", "TTOU", false, true, true, "to readers process group upon background tty write"); - AddSignal (23, "SIGIO", "IO", false, false, false, "input/output possible signal"); - AddSignal (24, "SIGXCPU", "XCPU", false, true, true, "exceeded CPU time limit"); - AddSignal (25, "SIGXFSZ", "XFSZ", false, true, true, "exceeded file size limit"); - AddSignal (26, "SIGVTALRM", "VTALRM", false, false, false, "virtual time alarm"); - AddSignal (27, "SIGPROF", "PROF", false, false, false, "profiling time alarm"); - AddSignal (28, "SIGWINCH", "WINCH", false, false, false, "window size changes"); - AddSignal (29, "SIGINFO", "INFO", false, true, true, "information request"); - AddSignal (30, "SIGUSR1", "USR1", false, true, true, "user defined signal 1"); - AddSignal (31, "SIGUSR2", "USR2", false, true, true, "user defined signal 2"); + // SIGNO NAME SHORT NAME SUPPRESS STOP NOTIFY DESCRIPTION + // ====== ============ ========== ======== ====== ====== =================================================== + AddSignal (1, "SIGHUP", "HUP", false, true , true , "hangup"); + AddSignal (2, "SIGINT", "INT", true , true , true , "interrupt"); + AddSignal (3, "SIGQUIT", "QUIT", false, true , true , "quit"); + AddSignal (4, "SIGILL", "ILL", false, true , true , "illegal instruction"); + AddSignal (5, "SIGTRAP", "TRAP", true , true , true , "trace trap (not reset when caught)"); + AddSignal (6, "SIGABRT", "ABRT", false, true , true , "abort()"); + AddSignal (7, "SIGEMT", "EMT", false, true , true , "pollable event"); + AddSignal (8, "SIGFPE", "FPE", false, true , true , "floating point exception"); + AddSignal (9, "SIGKILL", "KILL", false, true , true , "kill"); + AddSignal (10, "SIGBUS", "BUS", false, true , true , "bus error"); + AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation"); + AddSignal (12, "SIGSYS", "SYS", false, true , true , "bad argument to system call"); + AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write on a pipe with no one to read it"); + AddSignal (14, "SIGALRM", "ALRM", false, false, true , "alarm clock"); + AddSignal (15, "SIGTERM", "TERM", false, true , true , "software termination signal from kill"); + AddSignal (16, "SIGURG", "URG", false, false, false, "urgent condition on IO channel"); + AddSignal (17, "SIGSTOP", "STOP", true , true , true , "sendable stop signal not from tty"); + AddSignal (18, "SIGTSTP", "TSTP", false, true , true , "stop signal from tty"); + AddSignal (19, "SIGCONT", "CONT", false, true , true , "continue a stopped process"); + AddSignal (20, "SIGCHLD", "CHLD", false, false, true , "to parent on child stop or exit"); + AddSignal (21, "SIGTTIN", "TTIN", false, true , true , "to readers process group upon background tty read"); + AddSignal (22, "SIGTTOU", "TTOU", false, true , true , "to readers process group upon background tty write"); + AddSignal (23, "SIGIO", "IO", false, false, false, "input/output possible signal"); + AddSignal (24, "SIGXCPU", "XCPU", false, true , true , "exceeded CPU time limit"); + AddSignal (25, "SIGXFSZ", "XFSZ", false, true , true , "exceeded file size limit"); + AddSignal (26, "SIGVTALRM", "VTALRM", false, false, false, "virtual time alarm"); + AddSignal (27, "SIGPROF", "PROF", false, false, false, "profiling time alarm"); + AddSignal (28, "SIGWINCH", "WINCH", false, false, false, "window size changes"); + AddSignal (29, "SIGINFO", "INFO", false, true , true , "information request"); + AddSignal (30, "SIGUSR1", "USR1", false, true , true , "user defined signal 1"); + AddSignal (31, "SIGUSR2", "USR2", false, true , true , "user defined signal 2"); } void From granata.enrico at gmail.com Wed Jul 6 10:56:06 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Wed, 06 Jul 2011 15:56:06 -0000 Subject: [Lldb-commits] [lldb] r134492 - /lldb/trunk/source/Core/FormatManager.cpp Message-ID: <20110706155606.3E7DC2A6C12C@llvm.org> Author: enrico Date: Wed Jul 6 10:56:06 2011 New Revision: 134492 URL: http://llvm.org/viewvc/llvm-project?rev=134492&view=rev Log: Fixed some format names Modified: lldb/trunk/source/Core/FormatManager.cpp Modified: lldb/trunk/source/Core/FormatManager.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=134492&r1=134491&r2=134492&view=diff ============================================================================== --- lldb/trunk/source/Core/FormatManager.cpp (original) +++ lldb/trunk/source/Core/FormatManager.cpp Wed Jul 6 10:56:06 2011 @@ -52,10 +52,10 @@ { eFormatVectorOfUInt8 , '\0' , "uint8_t[]" }, { eFormatVectorOfSInt16 , '\0' , "int16_t[]" }, { eFormatVectorOfUInt16 , '\0' , "uint16_t[]" }, - { eFormatVectorOfSInt32 , '\0' , "int16_t[]" }, - { eFormatVectorOfUInt32 , '\0' , "uint16_t[]" }, - { eFormatVectorOfSInt64 , '\0' , "int16_t[]" }, - { eFormatVectorOfUInt64 , '\0' , "uint16_t[]" }, + { eFormatVectorOfSInt32 , '\0' , "int32_t[]" }, + { eFormatVectorOfUInt32 , '\0' , "uint32_t[]" }, + { eFormatVectorOfSInt64 , '\0' , "int64_t[]" }, + { eFormatVectorOfUInt64 , '\0' , "uint64_t[]" }, { eFormatVectorOfFloat32, '\0' , "float32[]" }, { eFormatVectorOfFloat64, '\0' , "float64[]" }, { eFormatVectorOfUInt128, '\0' , "uint128_t[]" }, From gclayton at apple.com Wed Jul 6 11:49:27 2011 From: gclayton at apple.com (Greg Clayton) Date: Wed, 06 Jul 2011 16:49:27 -0000 Subject: [Lldb-commits] [lldb] r134497 - in /lldb/trunk: include/lldb/API/SBError.h include/lldb/Core/ValueObject.h source/API/SBError.cpp source/API/SBValue.cpp source/Core/ValueObject.cpp test/lang/c/array_types/TestArrayTypes.py Message-ID: <20110706164927.7A9142A6C12C@llvm.org> Author: gclayton Date: Wed Jul 6 11:49:27 2011 New Revision: 134497 URL: http://llvm.org/viewvc/llvm-project?rev=134497&view=rev Log: Made the string representation for a SBValue return what "frame variable" would return instead of a less than helpful "name: '%s'" description. Make sure that when we ask for the error from a ValueObject object we first update the value if needed. Cleaned up some SB functions to use internal functions and not re-call through the public API when possible. Modified: lldb/trunk/include/lldb/API/SBError.h lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/source/API/SBError.cpp lldb/trunk/source/API/SBValue.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/test/lang/c/array_types/TestArrayTypes.py Modified: lldb/trunk/include/lldb/API/SBError.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBError.h?rev=134497&r1=134496&r2=134497&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBError.h (original) +++ lldb/trunk/include/lldb/API/SBError.h Wed Jul 6 11:49:27 2011 @@ -68,9 +68,6 @@ bool GetDescription (lldb::SBStream &description); - bool - GetDescription (lldb::SBStream &description) const; - protected: #ifndef SWIG Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134497&r1=134496&r2=134497&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Wed Jul 6 11:49:27 2011 @@ -326,7 +326,7 @@ // The functions below should NOT be modified by sublasses //------------------------------------------------------------------ const Error & - GetError() const; + GetError(); const ConstString & GetName() const; Modified: lldb/trunk/source/API/SBError.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBError.cpp?rev=134497&r1=134496&r2=134497&view=diff ============================================================================== --- lldb/trunk/source/API/SBError.cpp (original) +++ lldb/trunk/source/API/SBError.cpp Wed Jul 6 11:49:27 2011 @@ -218,35 +218,16 @@ { if (m_opaque_ap.get()) { - if (Success()) - description.Printf ("Status: Success"); + if (m_opaque_ap->Success()) + description.Printf ("success"); else { const char * err_string = GetCString(); - description.Printf ("Status: Error: %s", (err_string != NULL ? err_string : "")); + description.Printf ("error: %s", (err_string != NULL ? err_string : "")); } } else - description.Printf ("No value"); - - return true; -} - -bool -SBError::GetDescription (SBStream &description) const -{ - if (m_opaque_ap.get()) - { - if (Success()) - description.Printf ("Status: Success"); - else - { - const char * err_string = GetCString(); - description.Printf ("Status: Error: %s", (err_string != NULL ? err_string : "")); - } - } - else - description.Printf ("No value"); + description.Printf ("error: "); return true; } Modified: lldb/trunk/source/API/SBValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=134497&r1=134496&r2=134497&view=diff ============================================================================== --- lldb/trunk/source/API/SBValue.cpp (original) +++ lldb/trunk/source/API/SBValue.cpp Wed Jul 6 11:49:27 2011 @@ -599,21 +599,26 @@ { if (m_opaque_sp) { - // Don't call all these APIs and cause more logging! -// const char *name = GetName(); -// const char *type_name = GetTypeName (); -// size_t byte_size = GetByteSize (); -// uint32_t num_children = GetNumChildren (); -// bool is_stale = ValueIsStale (); -// description.Printf ("name: '%s', type: %s, size: %d", (name != NULL ? name : ""), -// (type_name != NULL ? type_name : ""), (int) byte_size); -// if (num_children > 0) -// description.Printf (", num_children: %d", num_children); -// -// if (is_stale) -// description.Printf (" [value is stale]"); - - description.Printf ("name: '%s'", m_opaque_sp->GetName().GetCString()); + uint32_t ptr_depth = 0; + uint32_t curr_depth = 0; + uint32_t max_depth = UINT32_MAX; + bool show_types = false; + bool show_location = false; + bool use_objc = false; + lldb::DynamicValueType use_dynamic = eNoDynamicValues; + bool scope_already_checked = false; + bool flat_output = false; + ValueObject::DumpValueObject (description.ref(), + m_opaque_sp.get(), + m_opaque_sp->GetName().GetCString(), + ptr_depth, + curr_depth, + max_depth, + show_types, show_location, + use_objc, + use_dynamic, + scope_already_checked, + flat_output); } else description.Printf ("No value"); Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134497&r1=134496&r2=134497&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Wed Jul 6 11:49:27 2011 @@ -212,8 +212,9 @@ } const Error & -ValueObject::GetError() const +ValueObject::GetError() { + UpdateValueIfNeeded(); return m_error; } @@ -1929,7 +1930,10 @@ { Thread *our_thread = m_process_sp->GetThreadList().FindThreadByIndexID (m_thread_id).get(); if (our_thread == NULL) - SetInvalid(); + { + //SetInvalid(); + m_exe_scope = m_process_sp.get(); + } else { m_exe_scope = our_thread; Modified: lldb/trunk/test/lang/c/array_types/TestArrayTypes.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/array_types/TestArrayTypes.py?rev=134497&r1=134496&r2=134497&view=diff ============================================================================== --- lldb/trunk/test/lang/c/array_types/TestArrayTypes.py (original) +++ lldb/trunk/test/lang/c/array_types/TestArrayTypes.py Wed Jul 6 11:49:27 2011 @@ -154,7 +154,7 @@ variable = frame.FindVariable("strings") var = repr(variable) self.expect(var, "Variable for 'strings' looks good with correct name", exe=False, - substrs = ["name: '%s'" % variable.GetName()]) + substrs = ["%s" % variable.GetName()]) self.DebugSBValue(frame, variable) self.assertTrue(variable.GetNumChildren() == 4, "Variable 'strings' should have 4 children") From jingham at apple.com Wed Jul 6 12:42:14 2011 From: jingham at apple.com (Jim Ingham) Date: Wed, 06 Jul 2011 17:42:14 -0000 Subject: [Lldb-commits] [lldb] r134505 - /lldb/trunk/source/Core/ValueObject.cpp Message-ID: <20110706174214.3B75D2A6C12C@llvm.org> Author: jingham Date: Wed Jul 6 12:42:14 2011 New Revision: 134505 URL: http://llvm.org/viewvc/llvm-project?rev=134505&view=rev Log: Set the EvaluationPoint's m_thread_id to the RIGHT invalid define... Modified: lldb/trunk/source/Core/ValueObject.cpp Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134505&r1=134504&r2=134505&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Wed Jul 6 12:42:14 2011 @@ -1805,7 +1805,7 @@ ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected): m_needs_update (true), m_first_update (true), - m_thread_id (LLDB_INVALID_UID), + m_thread_id (LLDB_INVALID_THREAD_ID), m_stop_id (0) { @@ -1931,8 +1931,7 @@ Thread *our_thread = m_process_sp->GetThreadList().FindThreadByIndexID (m_thread_id).get(); if (our_thread == NULL) { - //SetInvalid(); - m_exe_scope = m_process_sp.get(); + SetInvalid(); } else { From gclayton at apple.com Wed Jul 6 13:55:08 2011 From: gclayton at apple.com (Greg Clayton) Date: Wed, 06 Jul 2011 18:55:08 -0000 Subject: [Lldb-commits] [lldb] r134518 - in /lldb/trunk/source: Expression/ClangExpressionDeclMap.cpp Symbol/ClangASTImporter.cpp Message-ID: <20110706185508.CCB682A6C12C@llvm.org> Author: gclayton Date: Wed Jul 6 13:55:08 2011 New Revision: 134518 URL: http://llvm.org/viewvc/llvm-project?rev=134518&view=rev Log: Fixed an issue that was causing us to crash when evaluating expressions for objective C or C++ methods when "self" or "this" were in scope, but had invalid locations in a DWARF location list. The lack of a valid value caused us to use an invalid type value and then we tried to import that invalid value and we would crash. Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp lldb/trunk/source/Symbol/ClangASTImporter.cpp Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=134518&r1=134517&r2=134518&view=diff ============================================================================== --- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original) +++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Wed Jul 6 13:55:08 2011 @@ -1831,7 +1831,9 @@ lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); - if (!this_var) + if (!this_var || + !this_var->IsInScope(m_parser_vars->m_exe_ctx->frame) || + !this_var->LocationIsValidForFrame (m_parser_vars->m_exe_ctx->frame)) return; Type *this_type = this_var->GetType(); @@ -1886,7 +1888,9 @@ lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); - if (!self_var) + if (!self_var || + !self_var->IsInScope(m_parser_vars->m_exe_ctx->frame) || + !self_var->LocationIsValidForFrame (m_parser_vars->m_exe_ctx->frame)) return; Type *self_type = self_var->GetType(); Modified: lldb/trunk/source/Symbol/ClangASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTImporter.cpp?rev=134518&r1=134517&r2=134518&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTImporter.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTImporter.cpp Wed Jul 6 13:55:08 2011 @@ -18,23 +18,26 @@ ClangASTImporter::CopyType (clang::ASTContext *src_ast, clang::QualType type) { - MinionSP minion = GetMinion(src_ast, false); - - return minion->Import(type); + MinionSP minion_sp (GetMinion(src_ast, false)); + if (minion_sp) + return minion_sp->Import(type); + return QualType(); } clang::Decl * ClangASTImporter::CopyDecl (clang::ASTContext *src_ast, clang::Decl *decl) { - MinionSP minion; + MinionSP minion_sp; if (isa(decl)) - minion = GetMinion(src_ast, true); + minion_sp = GetMinion(src_ast, true); else - minion = GetMinion(src_ast, false); + minion_sp = GetMinion(src_ast, false); - return minion->Import(decl); + if (minion_sp) + return minion_sp->Import(decl); + return NULL; } const clang::DeclContext * @@ -53,9 +56,9 @@ if (!ClangASTContext::GetCompleteDecl(context_decl_origin.ctx, context_decl_origin.decl)) return NULL; - MinionSP minion = GetMinion(context_decl_origin.ctx, false); - - minion->ImportDefinition(context_decl_origin.decl); + MinionSP minion_sp (GetMinion(context_decl_origin.ctx, false)); + if (minion_sp) + minion_sp->ImportDefinition(context_decl_origin.decl); return decl_context; } From johnny.chen at apple.com Wed Jul 6 14:09:25 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 06 Jul 2011 19:09:25 -0000 Subject: [Lldb-commits] [lldb] r134519 - /lldb/trunk/examples/python/disasm.py Message-ID: <20110706190925.CF08A2A6C12C@llvm.org> Author: johnny Date: Wed Jul 6 14:09:25 2011 New Revision: 134519 URL: http://llvm.org/viewvc/llvm-project?rev=134519&view=rev Log: Remove unnecessary 'import' statement. Modified: lldb/trunk/examples/python/disasm.py Modified: lldb/trunk/examples/python/disasm.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/disasm.py?rev=134519&r1=134518&r2=134519&view=diff ============================================================================== --- lldb/trunk/examples/python/disasm.py (original) +++ lldb/trunk/examples/python/disasm.py Wed Jul 6 14:09:25 2011 @@ -11,7 +11,6 @@ import lldb import os import sys -import signal def disassemble_instructions (insts): for i in insts: From granata.enrico at gmail.com Wed Jul 6 14:27:11 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Wed, 06 Jul 2011 19:27:11 -0000 Subject: [Lldb-commits] [lldb] r134523 - /lldb/trunk/source/Core/Debugger.cpp Message-ID: <20110706192711.D06642A6C12C@llvm.org> Author: enrico Date: Wed Jul 6 14:27:11 2011 New Revision: 134523 URL: http://llvm.org/viewvc/llvm-project?rev=134523&view=rev Log: bug fix in summary strings: - ${*var[].something} was not working as expected options -p and -r now also work for type format add Modified: lldb/trunk/source/Core/Debugger.cpp Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134523&r1=134522&r2=134523&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Wed Jul 6 14:27:11 2011 @@ -954,6 +954,7 @@ const RegisterInfo *reg_info = NULL; RegisterContext *reg_ctx = NULL; bool do_deref_pointer = false; + bool did_deref_pointer = true; // Each variable must set success to true below... bool var_success = false; @@ -1046,18 +1047,37 @@ error).get(); } + if (var_name_final_if_array_range && (error.Fail() || !target)) + { + bool fake_do_deref = false; + target = ExpandExpressionPath(vobj, + exe_ctx->frame, + &fake_do_deref, + var_name_begin, + var_name_final_if_array_range, + error).get(); + + did_deref_pointer = false; + + if (target && ClangASTContext::IsArrayType(target->GetClangType())) + error.Clear(); + else + error.SetErrorString("error in expression"); + } + IFERROR_PRINT_IT else is_array_range = true; } - do_deref_pointer = false; // I have honored the request to deref + if (did_deref_pointer) + do_deref_pointer = false; // I have honored the request to deref } else break; - if (do_deref_pointer) + if (do_deref_pointer && !is_array_range) { // I have not deref-ed yet, let's do it // this happens when we are not going through GetValueForVariableExpressionPath @@ -1082,14 +1102,17 @@ if (close_bracket_position && (var_name_end-close_bracket_position > 1)) { int base_len = var_name_end-close_bracket_position; - special_directions = new char[8+base_len]; + special_directions = new char[7+base_len]; + int star_offset = (do_deref_pointer ? 1 : 0); special_directions[0] = '$'; - special_directions[1] = '{'; - special_directions[2] = 'v'; - special_directions[3] = 'a'; - special_directions[4] = 'r'; - memcpy(special_directions+5, close_bracket_position+1, base_len); - special_directions[base_len+7] = '\0'; + special_directions[1] = '{'; + if (do_deref_pointer) + special_directions[2] = '*'; + special_directions[2+star_offset] = 'v'; + special_directions[3+star_offset] = 'a'; + special_directions[4+star_offset] = 'r'; + memcpy(special_directions+5+star_offset, close_bracket_position+1, base_len); + special_directions[base_len+5+star_offset] = '\0'; #ifdef VERBOSE_FORMATPROMPT_OUTPUT printf("%s\n",special_directions); #endif //VERBOSE_FORMATPROMPT_OUTPUT @@ -1109,7 +1132,6 @@ index_lower, exe_ctx->frame, error).get(); - IFERROR_PRINT_IT if (!special_directions) From johnny.chen at apple.com Wed Jul 6 14:28:33 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 06 Jul 2011 19:28:33 -0000 Subject: [Lldb-commits] [lldb] r134524 - /lldb/trunk/include/lldb/API/SBDebugger.h Message-ID: <20110706192833.30BF22A6C12C@llvm.org> Author: johnny Date: Wed Jul 6 14:28:33 2011 New Revision: 134524 URL: http://llvm.org/viewvc/llvm-project?rev=134524&view=rev Log: Add docstrings for the primordial object -- SBDebugger. The swig "autodoc" feature to remove '*' from 'char *' will be handled by doing post-processing on the lldb.py module. Modified: lldb/trunk/include/lldb/API/SBDebugger.h Modified: lldb/trunk/include/lldb/API/SBDebugger.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBDebugger.h?rev=134524&r1=134523&r2=134524&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBDebugger.h (original) +++ lldb/trunk/include/lldb/API/SBDebugger.h Wed Jul 6 14:28:33 2011 @@ -15,8 +15,111 @@ namespace lldb { +#ifdef SWIG +%feature("docstring", +"SBDebugger is the primordial object that creates SBTargets and provides +access to them. It also manages the overall debugging experiences. + +For example (in example/disasm.py), + +import lldb +import os +import sys + +def disassemble_instructions (insts): + for i in insts: + print i + +... + +# Create a new debugger instance +debugger = lldb.SBDebugger.Create() + +# When we step or continue, don't return from the function until the process +# stops. We do this by setting the async mode to false. +debugger.SetAsync (False) + +# Create a target from a file and arch +print 'Creating a target for \'%s\'' % exe + +target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT) + +if target: + # If the target is valid set a breakpoint at main + main_bp = target.BreakpointCreateByName (fname, target.GetExecutable().GetFilename()); + + print main_bp + + # Launch the process. Since we specified synchronous mode, we won't return + # from this function until we hit the breakpoint at main + process = target.LaunchSimple (None, None, os.getcwd()) + + # Make sure the launch went ok + if process: + # Print some simple process info + state = process.GetState () + print process + if state == lldb.eStateStopped: + # Get the first thread + thread = process.GetThreadAtIndex (0) + if thread: + # Print some simple thread info + print thread + # Get the first frame + frame = thread.GetFrameAtIndex (0) + if frame: + # Print some simple frame info + print frame + function = frame.GetFunction() + # See if we have debug info (a function) + if function: + # We do have a function, print some info for the function + print function + # Now get all instructions for this function and print them + insts = function.GetInstructions(target) + disassemble_instructions (insts) + else: + # See if we have a symbol in the symbol table for where we stopped + symbol = frame.GetSymbol(); + if symbol: + # We do have a symbol, print some info for the symbol + print symbol + # Now get all instructions for this symbol and print them + insts = symbol.GetInstructions(target) + disassemble_instructions (insts) + + registerList = frame.GetRegisters() + print 'Frame registers (size of register set = %d):' % registerList.GetSize() + for value in registerList: + #print value + print '%s (number of children = %d):' % (value.GetName(), value.GetNumChildren()) + for child in value: + print 'Name: ', child.GetName(), ' Value: ', child.GetValue(frame) + + print 'Hit the breakpoint at main, enter to continue and wait for program to exit or \'Ctrl-D\'/\'quit\' to terminate the program' + next = sys.stdin.readline() + if not next or next.rstrip('\n') == 'quit': + print 'Terminating the inferior process...' + process.Kill() + else: + # Now continue to the program exit + process.Continue() + # When we return from the above function we will hopefully be at the + # program exit. Print out some process info + print process + elif state == lldb.eStateExited: + print 'Didn\'t hit the breakpoint at main, program has exited...' + else: + print 'Unexpected process state: %s, killing process...' % debugger.StateAsCString (state) + process.Kill() +" + ) SBDebugger; +#endif class SBDebugger { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: static void From gclayton at apple.com Wed Jul 6 16:01:19 2011 From: gclayton at apple.com (Greg Clayton) Date: Wed, 06 Jul 2011 21:01:19 -0000 Subject: [Lldb-commits] [lldb] r134534 - in /lldb/trunk: lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist Message-ID: <20110706210119.485D22A6C12C@llvm.org> Author: gclayton Date: Wed Jul 6 16:01:19 2011 New Revision: 134534 URL: http://llvm.org/viewvc/llvm-project?rev=134534&view=rev Log: Bumped Xcode project version for lldb-68. Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/resources/LLDB-Info.plist Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134534&r1=134533&r2=134534&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Jul 6 16:01:19 2011 @@ -3335,10 +3335,10 @@ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; + LLVM_BUILD_DIR = "/Volumes/work/gclayton/Documents/src/llvm/131657/llvm-debug"; LLVM_BUILD_DIR_ARCH = ""; - LLVM_CONFIGURATION = Release; - LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; + LLVM_CONFIGURATION = "Debug+Asserts"; + LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; ONLY_ACTIVE_ARCH = YES; VALID_ARCHS = "x86_64 i386"; }; @@ -3366,10 +3366,10 @@ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; + LLVM_BUILD_DIR = "/Volumes/work/gclayton/Documents/src/llvm/131657/llvm-debug"; LLVM_BUILD_DIR_ARCH = ""; - LLVM_CONFIGURATION = Release; - LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; + LLVM_CONFIGURATION = "Debug+Asserts"; + LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; VALID_ARCHS = "x86_64 i386"; }; name = Release; @@ -3418,10 +3418,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 68; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3470,11 +3470,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 68; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3521,8 +3521,8 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; - DYLIB_CURRENT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; + DYLIB_CURRENT_VERSION = 68; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3560,9 +3560,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 68; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3600,9 +3600,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 68; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3660,8 +3660,8 @@ GCC_WARN_UNUSED_VARIABLE = YES; LLVM_BUILD_DIR = "$(OBJROOT)/llvm"; LLVM_BUILD_DIR_ARCH = "$(CURRENT_ARCH)/"; - LLVM_CONFIGURATION = Release; - LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; + LLVM_CONFIGURATION = "Debug+Asserts"; + LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; VALID_ARCHS = "x86_64 i386"; }; name = BuildAndIntegration; @@ -3670,7 +3670,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3701,11 +3701,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 66; + DYLIB_CURRENT_VERSION = 68; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3830,7 +3830,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEBUG_INFORMATION_FORMAT = dwarf; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3862,7 +3862,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 66; + CURRENT_PROJECT_VERSION = 68; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", Modified: lldb/trunk/resources/LLDB-Info.plist URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/resources/LLDB-Info.plist?rev=134534&r1=134533&r2=134534&view=diff ============================================================================== --- lldb/trunk/resources/LLDB-Info.plist (original) +++ lldb/trunk/resources/LLDB-Info.plist Wed Jul 6 16:01:19 2011 @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 66 + 68 CFBundleName ${EXECUTABLE_NAME} From gclayton at apple.com Wed Jul 6 16:02:13 2011 From: gclayton at apple.com (Greg Clayton) Date: Wed, 06 Jul 2011 21:02:13 -0000 Subject: [Lldb-commits] [lldb] r134535 - /lldb/tags/lldb-68/ Message-ID: <20110706210213.4C6432A6C12C@llvm.org> Author: gclayton Date: Wed Jul 6 16:02:13 2011 New Revision: 134535 URL: http://llvm.org/viewvc/llvm-project?rev=134535&view=rev Log: lldb-68 Added: lldb/tags/lldb-68/ - copied from r134534, lldb/trunk/ From gclayton at apple.com Wed Jul 6 16:43:20 2011 From: gclayton at apple.com (Greg Clayton) Date: Wed, 06 Jul 2011 21:43:20 -0000 Subject: [Lldb-commits] [lldb] r134541 - /lldb/trunk/lldb.xcodeproj/project.pbxproj Message-ID: <20110706214320.A2E182A6C12C@llvm.org> Author: gclayton Date: Wed Jul 6 16:43:20 2011 New Revision: 134541 URL: http://llvm.org/viewvc/llvm-project?rev=134541&view=rev Log: Revert some Xcode project changes that I didn't intend to checkin. 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=134541&r1=134540&r2=134541&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Jul 6 16:43:20 2011 @@ -3335,10 +3335,10 @@ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - LLVM_BUILD_DIR = "/Volumes/work/gclayton/Documents/src/llvm/131657/llvm-debug"; + LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; LLVM_BUILD_DIR_ARCH = ""; - LLVM_CONFIGURATION = "Debug+Asserts"; - LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; + LLVM_CONFIGURATION = Release; + LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; ONLY_ACTIVE_ARCH = YES; VALID_ARCHS = "x86_64 i386"; }; @@ -3366,10 +3366,10 @@ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - LLVM_BUILD_DIR = "/Volumes/work/gclayton/Documents/src/llvm/131657/llvm-debug"; + LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; LLVM_BUILD_DIR_ARCH = ""; - LLVM_CONFIGURATION = "Debug+Asserts"; - LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; + LLVM_CONFIGURATION = Release; + LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; VALID_ARCHS = "x86_64 i386"; }; name = Release; @@ -3660,8 +3660,8 @@ GCC_WARN_UNUSED_VARIABLE = YES; LLVM_BUILD_DIR = "$(OBJROOT)/llvm"; LLVM_BUILD_DIR_ARCH = "$(CURRENT_ARCH)/"; - LLVM_CONFIGURATION = "Debug+Asserts"; - LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; + LLVM_CONFIGURATION = Release; + LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; VALID_ARCHS = "x86_64 i386"; }; name = BuildAndIntegration; From gclayton at apple.com Wed Jul 6 16:44:39 2011 From: gclayton at apple.com (Greg Clayton) Date: Wed, 06 Jul 2011 21:44:39 -0000 Subject: [Lldb-commits] [lldb] r134542 - /lldb/tags/lldb-68/lldb.xcodeproj/project.pbxproj Message-ID: <20110706214439.87EFD2A6C12C@llvm.org> Author: gclayton Date: Wed Jul 6 16:44:39 2011 New Revision: 134542 URL: http://llvm.org/viewvc/llvm-project?rev=134542&view=rev Log: Revert Xcode project changes that I didn't intend to commit. Modified: lldb/tags/lldb-68/lldb.xcodeproj/project.pbxproj Modified: lldb/tags/lldb-68/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-68/lldb.xcodeproj/project.pbxproj?rev=134542&r1=134541&r2=134542&view=diff ============================================================================== --- lldb/tags/lldb-68/lldb.xcodeproj/project.pbxproj (original) +++ lldb/tags/lldb-68/lldb.xcodeproj/project.pbxproj Wed Jul 6 16:44:39 2011 @@ -3335,10 +3335,10 @@ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - LLVM_BUILD_DIR = "/Volumes/work/gclayton/Documents/src/llvm/131657/llvm-debug"; + LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; LLVM_BUILD_DIR_ARCH = ""; - LLVM_CONFIGURATION = "Debug+Asserts"; - LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; + LLVM_CONFIGURATION = Release; + LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; ONLY_ACTIVE_ARCH = YES; VALID_ARCHS = "x86_64 i386"; }; @@ -3366,10 +3366,10 @@ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - LLVM_BUILD_DIR = "/Volumes/work/gclayton/Documents/src/llvm/131657/llvm-debug"; + LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; LLVM_BUILD_DIR_ARCH = ""; - LLVM_CONFIGURATION = "Debug+Asserts"; - LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; + LLVM_CONFIGURATION = Release; + LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; VALID_ARCHS = "x86_64 i386"; }; name = Release; @@ -3660,8 +3660,8 @@ GCC_WARN_UNUSED_VARIABLE = YES; LLVM_BUILD_DIR = "$(OBJROOT)/llvm"; LLVM_BUILD_DIR_ARCH = "$(CURRENT_ARCH)/"; - LLVM_CONFIGURATION = "Debug+Asserts"; - LLVM_SOURCE_DIR = /Volumes/work/gclayton/Documents/src/llvm/131657/llvm; + LLVM_CONFIGURATION = Release; + LLVM_SOURCE_DIR = "$(SRCROOT)/llvm"; VALID_ARCHS = "x86_64 i386"; }; name = BuildAndIntegration; From johnny.chen at apple.com Wed Jul 6 16:55:45 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 06 Jul 2011 21:55:45 -0000 Subject: [Lldb-commits] [lldb] r134543 - /lldb/trunk/scripts/Python/modify-python-lldb.py Message-ID: <20110706215545.5A9C62A6C12C@llvm.org> Author: johnny Date: Wed Jul 6 16:55:45 2011 New Revision: 134543 URL: http://llvm.org/viewvc/llvm-project?rev=134543&view=rev Log: Add post-processing step to transform the docstring from 'char', i.e., 'char *', to 'str', i.e., Python string. Modified: lldb/trunk/scripts/Python/modify-python-lldb.py Modified: lldb/trunk/scripts/Python/modify-python-lldb.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/modify-python-lldb.py?rev=134543&r1=134542&r2=134543&view=diff ============================================================================== --- lldb/trunk/scripts/Python/modify-python-lldb.py (original) +++ lldb/trunk/scripts/Python/modify-python-lldb.py Wed Jul 6 16:55:45 2011 @@ -13,6 +13,10 @@ # '#endif', the '#ifdef SWIG', the c comment marker, the trailing blank (SPC's) # line, and the doxygen comment start marker. # +# In addition to the 'residues' removal during the cleanup step, it also +# transforms the 'char' data type (which was actually 'char *' but the 'autodoc' +# feature of swig removes ' *' from it into 'str' (as a Python str type). +# # It also calls SBDebugger.Initialize() to initialize the lldb debugger # subsystem. # @@ -26,7 +30,9 @@ # print "output_name is '" + output_name + "'" +# # Residues to be removed. +# c_endif_swig = "#endif" c_ifdef_swig = "#ifdef SWIG" c_comment_marker = "//------------" @@ -37,6 +43,17 @@ # When bracketed by the lines, the CLEANUP_DOCSTRING state (see below) is ON. toggle_docstring_cleanup_line = ' """' +def char_to_str_xform(line): + """This transforms the 'char', i.e, 'char *' to 'str', Python string.""" + line = line.replace(' char', ' str') + line = line.replace('char ', 'str ') + return line + +# +# The one-liner docstring also needs char_to_str transformation, btw. +# +one_liner_docstring_pattern = re.compile('^ """.*"""$') + # # lldb_iter() should appear before our first SB* class definition. # @@ -236,9 +253,16 @@ if doxygen_comment_match: line = line.replace(doxygen_comment_match.group(1), '', 1) + line = char_to_str_xform(line) + # Note that the transition out of CLEANUP_DOCSTRING is handled at the # beginning of this function already. + # This deals with one-liner docstring, for example, SBThread.GetName: + # """GetName(self) -> char""". + if one_liner_docstring_pattern.match(line): + line = char_to_str_xform(line) + # Look for 'def IsValid(*args):', and once located, add implementation # of truth value testing for this object by delegation. if isvalid_pattern.search(line): From johnny.chen at apple.com Wed Jul 6 17:11:39 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 06 Jul 2011 22:11:39 -0000 Subject: [Lldb-commits] [lldb] r134551 - /lldb/trunk/test/python_api/default-constructor/sb_type.py Message-ID: <20110706221139.1C9F72A6C12C@llvm.org> Author: johnny Date: Wed Jul 6 17:11:38 2011 New Revision: 134551 URL: http://llvm.org/viewvc/llvm-project?rev=134551&view=rev Log: Add fuzz calls for SBType::IsPointerType(void *opaque_type). Modified: lldb/trunk/test/python_api/default-constructor/sb_type.py Modified: lldb/trunk/test/python_api/default-constructor/sb_type.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/default-constructor/sb_type.py?rev=134551&r1=134550&r2=134551&view=diff ============================================================================== --- lldb/trunk/test/python_api/default-constructor/sb_type.py (original) +++ lldb/trunk/test/python_api/default-constructor/sb_type.py Wed Jul 6 17:11:38 2011 @@ -16,4 +16,6 @@ obj.IsAPointerType() obj.GetPointeeType() obj.GetDescription(lldb.SBStream()) + obj.IsPointerType(None) + lldb.SBType.IsPointerType(None) From johnny.chen at apple.com Wed Jul 6 17:23:24 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 06 Jul 2011 22:23:24 -0000 Subject: [Lldb-commits] [lldb] r134553 - /lldb/trunk/include/lldb/API/SBEvent.h Message-ID: <20110706222324.3B59F2A6C12C@llvm.org> Author: johnny Date: Wed Jul 6 17:23:24 2011 New Revision: 134553 URL: http://llvm.org/viewvc/llvm-project?rev=134553&view=rev Log: SWIG doesn't need two methods of the same name 'GetDescription' but differ in the presence of 'const'. Ifndef the non-const one out. Modified: lldb/trunk/include/lldb/API/SBEvent.h Modified: lldb/trunk/include/lldb/API/SBEvent.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBEvent.h?rev=134553&r1=134552&r2=134553&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBEvent.h (original) +++ lldb/trunk/include/lldb/API/SBEvent.h Wed Jul 6 17:23:24 2011 @@ -61,8 +61,10 @@ static const char * GetCStringFromEvent (const lldb::SBEvent &event); +#ifndef SWIG bool GetDescription (lldb::SBStream &description); +#endif bool GetDescription (lldb::SBStream &description) const; From johnny.chen at apple.com Wed Jul 6 18:23:53 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 06 Jul 2011 23:23:53 -0000 Subject: [Lldb-commits] [lldb] r134560 - in /lldb/trunk/include/lldb/API: SBAddress.h SBFunction.h Message-ID: <20110706232353.5D3A52A6C12C@llvm.org> Author: johnny Date: Wed Jul 6 18:23:53 2011 New Revision: 134560 URL: http://llvm.org/viewvc/llvm-project?rev=134560&view=rev Log: Add class docstrings with example usage for SBFunction and SBAddress. Modified: lldb/trunk/include/lldb/API/SBAddress.h lldb/trunk/include/lldb/API/SBFunction.h Modified: lldb/trunk/include/lldb/API/SBAddress.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBAddress.h?rev=134560&r1=134559&r2=134560&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBAddress.h (original) +++ lldb/trunk/include/lldb/API/SBAddress.h Wed Jul 6 18:23:53 2011 @@ -15,8 +15,47 @@ namespace lldb { +#ifdef SWIG +%feature("docstring", +"A section + offset based address class. + +The SBAddress class allows addresses to be relative to a section +that can move during runtime due to images (executables, shared +libraries, bundles, frameworks) being loaded at different +addresses than the addresses found in the object file that +represents them on disk. There are currently two types of addresses +for a section: + o file addresses + o load addresses + +File addresses represents the virtual addresses that are in the 'on +disk' object files. These virtual addresses are converted to be +relative to unique sections scoped to the object file so that +when/if the addresses slide when the images are loaded/unloaded +in memory, we can easily track these changes without having to +update every object (compile unit ranges, line tables, function +address ranges, lexical block and inlined subroutine address +ranges, global and static variables) each time an image is loaded or +unloaded. + +Load addresses represents the virtual addresses where each section +ends up getting loaded at runtime. Before executing a program, it +is common for all of the load addresses to be unresolved. When a +DynamicLoader plug-in receives notification that shared libraries +have been loaded/unloaded, the load addresses of the main executable +and any images (shared libraries) will be resolved/unresolved. When +this happens, breakpoints that are in one of these sections can be +set/cleared. + +See docstring of SBFunction for example usage of SBAddress. +" + ) SBAddress; +#endif class SBAddress { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: SBAddress (); Modified: lldb/trunk/include/lldb/API/SBFunction.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBFunction.h?rev=134560&r1=134559&r2=134560&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBFunction.h (original) +++ lldb/trunk/include/lldb/API/SBFunction.h Wed Jul 6 18:23:53 2011 @@ -18,7 +18,40 @@ #ifdef SWIG %feature("docstring", - "Represents a generic function, which can be inlined or not." +"Represents a generic function, which can be inlined or not. + +For example (in test/lldbutil.py, but slightly modified for doc purpose), + + ... + + frame = thread.GetFrameAtIndex(i) + addr = frame.GetPCAddress() + load_addr = addr.GetLoadAddress(target) + function = frame.GetFunction() + mod_name = frame.GetModule().GetFileSpec().GetFilename() + + if not function: + # No debug info for 'function'. + symbol = frame.GetSymbol() + file_addr = addr.GetFileAddress() + start_addr = symbol.GetStartAddress().GetFileAddress() + symbol_name = symbol.GetName() + symbol_offset = file_addr - start_addr + print >> output, ' frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}'.format( + num=i, addr=load_addr, mod=mod_name, symbol=symbol_name, offset=symbol_offset) + else: + # Debug info is available for 'function'. + func_name = frame.GetFunctionName() + file_name = frame.GetLineEntry().GetFileSpec().GetFilename() + line_num = frame.GetLineEntry().GetLine() + print >> output, ' frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}'.format( + num=i, addr=load_addr, mod=mod_name, + func='%s [inlined]' % func_name] if frame.IsInlined() else func_name, + file=file_name, line=line_num, args=get_args_as_string(frame, showFuncName=False)) + + ... + +" ) SBFunction; #endif class SBFunction From johnny.chen at apple.com Wed Jul 6 19:14:13 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 00:14:13 -0000 Subject: [Lldb-commits] [lldb] r134571 - in /lldb/trunk/include/lldb/API: SBBreakpoint.h SBBreakpointLocation.h SBFunction.h SBThread.h Message-ID: <20110707001413.6D9C92A6C12C@llvm.org> Author: johnny Date: Wed Jul 6 19:14:13 2011 New Revision: 134571 URL: http://llvm.org/viewvc/llvm-project?rev=134571&view=rev Log: Add class docstrings with example usage for SBBreakpoint and SBBreakpointLocation. Modified: lldb/trunk/include/lldb/API/SBBreakpoint.h lldb/trunk/include/lldb/API/SBBreakpointLocation.h lldb/trunk/include/lldb/API/SBFunction.h lldb/trunk/include/lldb/API/SBThread.h Modified: lldb/trunk/include/lldb/API/SBBreakpoint.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpoint.h?rev=134571&r1=134570&r2=134571&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBBreakpoint.h (original) +++ lldb/trunk/include/lldb/API/SBBreakpoint.h Wed Jul 6 19:14:13 2011 @@ -15,8 +15,70 @@ namespace lldb { +#ifdef SWIG +%feature("docstring", +"Represents a logical breakpoint and its associated settings. + +For example (from test/functionalities/breakpoint/breakpoint_ignore_count/ +TestBreakpointIgnoreCount.py), + + def breakpoint_ignore_count_python(self): + '''Use Python APIs to set breakpoint ignore count.''' + exe = os.path.join(os.getcwd(), 'a.out') + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Get the breakpoint location from breakpoint after we verified that, + # indeed, it has one location. + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and + location.IsEnabled(), + VALID_BREAKPOINT_LOCATION) + + # Set the ignore count on the breakpoint location. + location.SetIgnoreCount(2) + self.assertTrue(location.GetIgnoreCount() == 2, + 'SetIgnoreCount() works correctly') + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and + # frame#2 should be on main.c:48. + #lldbutil.print_stacktraces(process) + from lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue(thread != None, 'There should be a thread stopped due to breakpoint') + frame0 = thread.GetFrameAtIndex(0) + frame1 = thread.GetFrameAtIndex(1) + frame2 = thread.GetFrameAtIndex(2) + self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and + frame1.GetLineEntry().GetLine() == self.line3 and + frame2.GetLineEntry().GetLine() == self.line4, + STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT) + + # The hit count for the breakpoint should be 3. + self.assertTrue(breakpoint.GetHitCount() == 3) + + process.Continue() + +" + ) SBBreakpoint; +#endif class SBBreakpoint { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: typedef bool (*BreakpointHitCallback) (void *baton, Modified: lldb/trunk/include/lldb/API/SBBreakpointLocation.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBBreakpointLocation.h?rev=134571&r1=134570&r2=134571&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBBreakpointLocation.h (original) +++ lldb/trunk/include/lldb/API/SBBreakpointLocation.h Wed Jul 6 19:14:13 2011 @@ -15,8 +15,24 @@ namespace lldb { +#ifdef SWIG +%feature("docstring", +"Represents one unique instance (by address) of a logical breakpoint. + +A breakpoint location is defined by the breakpoint that produces it, +and the address that resulted in this particular instantiation. +Each breakpoint location has its settable options. + +SBBreakpoint contains SBBreakpointLocation(s). See docstring of SBBreakpoint +for retrieval of an SBBreakpointLocation from an SBBreakpoint. +" + ) SBBreakpointLocation; +#endif class SBBreakpointLocation { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: SBBreakpointLocation (); @@ -87,7 +103,9 @@ SBBreakpoint GetBreakpoint (); +#ifndef SWIG SBBreakpointLocation (const lldb::BreakpointLocationSP &break_loc_sp); +#endif private: friend class SBBreakpoint; Modified: lldb/trunk/include/lldb/API/SBFunction.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBFunction.h?rev=134571&r1=134570&r2=134571&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBFunction.h (original) +++ lldb/trunk/include/lldb/API/SBFunction.h Wed Jul 6 19:14:13 2011 @@ -20,7 +20,7 @@ %feature("docstring", "Represents a generic function, which can be inlined or not. -For example (in test/lldbutil.py, but slightly modified for doc purpose), +For example (from test/lldbutil.py, but slightly modified for doc purpose), ... Modified: lldb/trunk/include/lldb/API/SBThread.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=134571&r1=134570&r2=134571&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBThread.h (original) +++ lldb/trunk/include/lldb/API/SBThread.h Wed Jul 6 19:14:13 2011 @@ -22,7 +22,7 @@ %feature("docstring", "Represents a thread of execution. SBProcess contains SBThread(s). -For example (in test/lldbutil.py), +For example (from test/lldbutil.py), # ================================================== # Utility functions related to Threads and Processes From granata.enrico at gmail.com Wed Jul 6 19:38:40 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Thu, 07 Jul 2011 00:38:40 -0000 Subject: [Lldb-commits] [lldb] r134574 - in /lldb/trunk: include/lldb/Interpreter/CommandInterpreter.h include/lldb/Interpreter/CommandObject.h include/lldb/lldb-enumerations.h source/Commands/CommandObjectType.cpp source/Interpreter/CommandInterpreter.cpp source/Interpreter/CommandObject.cpp Message-ID: <20110707003841.07FAA2A6C12C@llvm.org> Author: enrico Date: Wed Jul 6 19:38:40 2011 New Revision: 134574 URL: http://llvm.org/viewvc/llvm-project?rev=134574&view=rev Log: new detailed descriptions for type summary add and type format add some changes to the help system code for better display of long help text -p and -r flags now also work for type format add Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h lldb/trunk/include/lldb/Interpreter/CommandObject.h lldb/trunk/include/lldb/lldb-enumerations.h lldb/trunk/source/Commands/CommandObjectType.cpp lldb/trunk/source/Interpreter/CommandInterpreter.cpp lldb/trunk/source/Interpreter/CommandObject.cpp Modified: lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h?rev=134574&r1=134573&r2=134574&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandInterpreter.h Wed Jul 6 19:38:40 2011 @@ -242,6 +242,18 @@ const char *separator, const char *help_text, uint32_t max_word_len); + + // this mimics OutputFormattedHelpText but it does perform a much simpler + // formatting, basically ensuring line alignment. This is only good if you have + // some complicated layout for your help text and want as little help as reasonable + // in properly displaying it. Most of the times, you simply want to type some text + // and have it printed in a reasonable way on screen. If so, use OutputFormattedHelpText + void + OutputHelpText (Stream &stream, + const char *command_word, + const char *separator, + const char *help_text, + uint32_t max_word_len); Debugger & GetDebugger () Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandObject.h?rev=134574&r1=134573&r2=134574&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandObject.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandObject.h Wed Jul 6 19:38:40 2011 @@ -29,12 +29,36 @@ typedef const char *(ArgumentHelpCallbackFunction) (); + struct ArgumentHelpCallback + { + ArgumentHelpCallbackFunction *help_callback; + bool self_formatting; + ArgumentHelpCallback(ArgumentHelpCallbackFunction *p, + bool f = false) : + help_callback(p), + self_formatting(f) + { + } + + const char* + operator () () const + { + return (*help_callback)(); + } + + operator bool() const + { + return (help_callback != NULL); + } + + }; + struct ArgumentTableEntry // Entries in the main argument information table { lldb::CommandArgumentType arg_type; const char *arg_name; CommandCompletions::CommonCompletionTypes completion_type; - ArgumentHelpCallbackFunction *help_function; + ArgumentHelpCallback help_function; const char *help_text; }; Modified: lldb/trunk/include/lldb/lldb-enumerations.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/lldb-enumerations.h?rev=134574&r1=134573&r2=134574&view=diff ============================================================================== --- lldb/trunk/include/lldb/lldb-enumerations.h (original) +++ lldb/trunk/include/lldb/lldb-enumerations.h Wed Jul 6 19:38:40 2011 @@ -351,7 +351,6 @@ eArgTypeExprFormat, eArgTypeFilename, eArgTypeFormat, - eArgTypeFormatString, eArgTypeFrameIndex, eArgTypeFullName, eArgTypeFunctionName, @@ -387,6 +386,7 @@ eArgTypeSourceFile, eArgTypeSortOrder, eArgTypeStartAddress, + eArgTypeSummaryString, eArgTypeSymbol, eArgTypeThreadID, eArgTypeThreadIndex, Modified: lldb/trunk/source/Commands/CommandObjectType.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=134574&r1=134573&r2=134574&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectType.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectType.cpp Wed Jul 6 19:38:40 2011 @@ -63,6 +63,12 @@ case 'f': error = Args::StringToFormat(option_arg, m_format, NULL); break; + case 'p': + m_skip_pointers = true; + break; + case 'r': + m_skip_references = true; + break; default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -76,6 +82,8 @@ { m_cascade = true; m_format = eFormatInvalid; + m_skip_pointers = false; + m_skip_references = false; } const OptionDefinition* @@ -92,6 +100,8 @@ bool m_cascade; lldb::Format m_format; + bool m_skip_references; + bool m_skip_pointers; }; CommandOptions m_options; @@ -118,6 +128,34 @@ type_arg.push_back (type_style_arg); m_arguments.push_back (type_arg); + + SetHelpLong( + "Some examples of using this command.\n" + "We use as reference the following snippet of code:\n" + "\n" + "typedef int Aint;\n" + "typedef float Afloat;\n" + "typedef Aint Bint;\n" + "typedef Afloat Bfloat;\n" + "\n" + "Aint ix = 5;\n" + "Bint iy = 5;\n" + "\n" + "Afloat fx = 3.14;\n" + "BFloat fy = 3.14;\n" + "\n" + "Typing:\n" + "type format add -f hex AInt\n" + "frame variable iy\n" + "will produce an hex display of iy, because no formatter is available for Bint and the one for Aint is used instead\n" + "To prevent this type\n" + "type format add -f hex -C no AInt\n" + "\n" + "A similar reasoning applies to\n" + "type format add -f hex -C no float -p\n" + "which now prints all floats and float&s as hexadecimal, but does not format float*s\n" + "and does not change the default display for Afloat and Bfloat objects.\n" + ); } ~CommandObjectTypeFormatAdd () @@ -145,7 +183,10 @@ ValueFormatSP entry; - entry.reset(new ValueFormat(m_options.m_format,m_options.m_cascade)); + entry.reset(new ValueFormat(m_options.m_format, + m_options.m_cascade, + m_options.m_skip_pointers, + m_options.m_skip_references)); // now I have a valid format, let's add it to every type @@ -172,6 +213,8 @@ { { LLDB_OPT_SET_ALL, false, "cascade", 'C', required_argument, NULL, 0, eArgTypeBoolean, "If true, cascade to derived typedefs."}, { LLDB_OPT_SET_ALL, false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format to use to display this type."}, + { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for pointers-to-type objects."}, + { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -343,9 +386,11 @@ { if (regex == NULL || regex->Execute(type)) { - result->GetOutputStream().Printf ("%s: %s%s\n", type, + result->GetOutputStream().Printf ("%s: %s%s%s%s\n", type, FormatManager::GetFormatAsCString (entry->m_format), - entry->m_cascades ? "" : " (not cascading)"); + entry->m_cascades ? "" : " (not cascading)", + entry->m_skip_pointers ? " (skip pointers)" : "", + entry->m_skip_references ? " (skip references)" : ""); } return true; } @@ -489,6 +534,62 @@ type_arg.push_back (type_style_arg); m_arguments.push_back (type_arg); + + SetHelpLong( + "Some examples of using this command.\n" + "We use as reference the following snippet of code:\n" + "struct JustADemo\n" + "{\n" + "int* ptr;\n" + "float value;\n" + "JustADemo(int p = 1, float v = 0.1) : ptr(new int(p)), value(v) {}\n" + "};\n" + "JustADemo object(42,3.14);\n" + "struct AnotherDemo : public JustADemo\n" + "{\n" + "uint8_t byte;\n" + "AnotherDemo(uint8_t b = 'E', int p = 1, float v = 0.1) : JustADemo(p,v), byte(b) {}\n" + "};\n" + "AnotherDemo *another_object = new AnotherDemo('E',42,3.14);\n" + "\n" + "type summary add -f \"the answer is ${*var.ptr}\" JustADemo\n" + "when typing frame variable object you will get \"the answer is 42\"\n" + "type summary add -f \"the answer is ${*var.ptr}, and the question is ${var.value}\" JustADemo\n" + "when typing frame variable object you will get \"the answer is 42 and the question is 3.14\"\n" + "\n" + "Alternatively, you could also say\n" + "type summary add -f \"${var%V} -> ${*var}\" \"int *\"\n" + "and replace the above summary string with\n" + "type summary add -f \"the answer is ${var.ptr}, and the question is ${var.value}\" JustADemo\n" + "to obtain a similar result\n" + "\n" + "To add a summary valid for both JustADemo and AnotherDemo you can use the scoping operator, as in:\n" + "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes\n" + "\n" + "This will be used for both variables of type JustADemo and AnotherDemo. To prevent this, change the -C to read -C no\n" + "If you do not want pointers to be shown using that summary, you can use the -p option, as in:\n" + "type summary add -f \"${var.ptr}, ${var.value},{${var.byte}}\" JustADemo -C yes -p\n" + "A similar option -r exists for references.\n" + "\n" + "If you simply want a one-line summary of the content of your variable, without typing an explicit string to that effect\n" + "you can use the -c option, without giving any summary string:\n" + "type summary add -c JustADemo\n" + "frame variable object\n" + "the output being similar to (ptr=0xsomeaddress, value=3.14)\n" + "\n" + "If you want to display some summary text, but also expand the structure of your object, you can add the -e option, as in:\n" + "type summary add -e -f \"*ptr = ${*var.ptr}\" JustADemo\n" + "Here the value of the int* is displayed, followed by the standard LLDB sequence of children objects, one per line.\n" + "to get an output like:\n" + "\n" + "*ptr = 42 {\n" + " ptr = 0xsomeaddress\n" + " value = 3.14\n" + "}\n" + "\n" + "A command you may definitely want to try if you're doing C++ debugging is:\n" + "type summary add -f \"${var._M_dataplus._M_p}\" std::string\n" + ); } ~CommandObjectTypeSummaryAdd () @@ -574,7 +675,7 @@ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', no_argument, NULL, 0, eArgTypeBoolean, "Don't use this format for references-to-type objects."}, { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeBoolean, "Type names are actually regular expressions."}, { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeBoolean, "If true, inline all child values into summary string."}, - { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeFormatString, "Format string used to display text and object contents."}, + { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; Modified: lldb/trunk/source/Interpreter/CommandInterpreter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandInterpreter.cpp?rev=134574&r1=134573&r2=134574&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandInterpreter.cpp (original) +++ lldb/trunk/source/Interpreter/CommandInterpreter.cpp Wed Jul 6 19:38:40 2011 @@ -2014,6 +2014,49 @@ } void +CommandInterpreter::OutputHelpText (Stream &strm, + const char *word_text, + const char *separator, + const char *help_text, + uint32_t max_word_len) +{ + int indent_size = max_word_len + strlen (separator) + 2; + + strm.IndentMore (indent_size); + + StreamString text_strm; + text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text); + + const uint32_t max_columns = m_debugger.GetTerminalWidth(); + bool first_line = true; + + size_t len = text_strm.GetSize(); + const char *text = text_strm.GetData(); + + uint32_t chars_left = max_columns; + + for (uint32_t i = 0; i < len; i++) + { + if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n') + { + first_line = false; + chars_left = max_columns - indent_size; + strm.EOL(); + strm.Indent(); + } + else + { + strm.PutChar(text[i]); + chars_left--; + } + + } + + strm.EOL(); + strm.IndentLess(indent_size); +} + +void CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word, StringList &commands_found, StringList &commands_help) { Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=134574&r1=134573&r2=134574&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Wed Jul 6 19:38:40 2011 @@ -469,9 +469,20 @@ StreamString name_str; name_str.Printf ("<%s>", entry->arg_name); - if (entry->help_function != NULL) - interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", (*(entry->help_function)) (), - name_str.GetSize()); + if (entry->help_function) + { + const char* help_text = entry->help_function(); + if (!entry->help_function.self_formatting) + { + interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text, + name_str.GetSize()); + } + else + { + interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text, + name_str.GetSize()); + } + } else interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize()); } @@ -630,32 +641,61 @@ static const char * FormatHelpTextCallback () { + + static char* help_text_ptr = NULL; + + if (help_text_ptr) + return help_text_ptr; + StreamString sstr; sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n"; for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1)) { + if (f != eFormatDefault) + sstr.PutChar('\n'); + char format_char = FormatManager::GetFormatAsFormatChar(f); if (format_char) sstr.Printf("'%c' or ", format_char); - sstr.Printf ("\"%s\" ; ", FormatManager::GetFormatAsCString(f)); + sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f)); } sstr.Flush(); std::string data = sstr.GetString(); - char* help = new char[data.length()+1]; + help_text_ptr = new char[data.length()+1]; - data.copy(help, data.length()); + data.copy(help_text_ptr, data.length()); - return help; + return help_text_ptr; } static const char * -FormatStringHelpTextCallback() +SummaryStringHelpTextCallback() { - return "Ask me tomorrow"; + return + "A summary string is a way to extract information from variables in order to present them using a summary.\n" + "Summary strings contain static text, variables, scopes and control sequences:\n" + " - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n" + " - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n" + " - Scopes are any sequence of text between { and }. Anything included in a scope will only appear in the output summary if there were no errors.\n" + " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n" + "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n" + "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n" + "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type" + " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be" + " ${var.x.y}). In expression paths you can use either . or -> without any difference in meaning. You can also use ${*var followed by an expression path and in that case" + " the object referred by the path will be dereferenced before being displayed. If the object is not a pointer, doing so will cause an error.\n" + "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed." + "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression" + " path refers to:\n" + " - if it is a scalar type (any basic type like int, float, ...) the expression is a bitfield, i.e. the bits indicated by the indexing operator are extracted out of the number" + " and displayed as an individual variable\n" + " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are" + " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n" + "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1."; } const char * @@ -693,8 +733,7 @@ { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, NULL, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, NULL, "The name of a file (can include path)." }, - { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, FormatHelpTextCallback, NULL }, - { eArgTypeFormatString, "format-string", CommandCompletions::eNoCompletion, FormatStringHelpTextCallback, NULL }, + { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, CommandObject::ArgumentHelpCallback(FormatHelpTextCallback, true), NULL }, { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, NULL, "Index into a thread's list of frames." }, { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, NULL, "The name of a function." }, @@ -730,6 +769,7 @@ { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, NULL, "The name of a source file.." }, { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, NULL, "Specify a sort order when dumping lists." }, { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, + { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, CommandObject::ArgumentHelpCallback(SummaryStringHelpTextCallback, true), NULL }, { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, NULL, "Any symbol name (function name, variable, argument, etc.)" }, { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, NULL, "Thread ID number." }, { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, NULL, "Index into the process' list of threads." }, From granata.enrico at gmail.com Wed Jul 6 19:39:56 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Thu, 07 Jul 2011 00:39:56 -0000 Subject: [Lldb-commits] [lldb] r134575 - /lldb/trunk/www/varformats.html Message-ID: <20110707003956.209002A6C12C@llvm.org> Author: enrico Date: Wed Jul 6 19:39:55 2011 New Revision: 134575 URL: http://llvm.org/viewvc/llvm-project?rev=134575&view=rev Log: new webpage describing type command Added: lldb/trunk/www/varformats.html (with props) Added: lldb/trunk/www/varformats.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/varformats.html?rev=134575&view=auto ============================================================================== --- lldb/trunk/www/varformats.html (added) +++ lldb/trunk/www/varformats.html Wed Jul 6 19:39:55 2011 @@ -0,0 +1,576 @@ + + + + + +LLDB Homepage + + + +
+ The LLDB Debugger +
+ +
+
+ + +
+
+

Variable display

+
+

LLDB was recently modified to allow users to define the + format of the variables display on a per-type basis.

+ +

Usually, when you type frame + variable or run some expression + LLDB will automatically choose the best way + to display your results according to its own + logic:

(SimpleWithPointers [3]) + sparray = {
(SimpleWithPointers) [0] = {
+ (int *) x = 0x00000001001000f0
(float *) y = + 0x0000000100100100
(char *) z = + 0x0000000100100110 "3"
+ }
+ (SimpleWithPointers) [1] = {
(int *) x = + 0x0000000100100120
(float *) y = + 0x0000000100100130
(char *) z = + 0x0000000100100140 "6"
+ }
+ (SimpleWithPointers) [2] = {
(int *) x = + 0x0000000100100150
(float *) y = + 0x0000000100100160
(char *) z = + 0x0000000100100170 "9"
+ }
+ }
+

+ +

However, there are cases in which your idea of + best is different from LLDB's. Now there are two + new commands that enable you to give hints to the debugger + as to how datatypes should be displayed.

+ +

Using them you can obtain a format like this one for + sparray, instead of the default shown above: +

+ +

+ + (SimpleWithPointers [3]) sparray = {
+ [0] = (x=0x00000001001000f0 -> -1, y=0x0000000100100100 -> -2, z="3")
+ [1] = (x=0x0000000100100120 -> -4, y=0x0000000100100130 -> -5, z="6")
+ [2] = (x=0x0000000100100150 -> -7, y=0x0000000100100160 -> -8, z="9")
+}
+
+

+

Variable formatting can be set using the type commands:

+

type format

+

type summary

+

Each of these commands has four subcommands:

+

add: adds a new entry

+

delete: deletes an existing entry

+

list: provides a listing of all entries

+

clear: deletes all entries

+ +
+ +
+ +
+

type format

+
+ +

Type formats enable you to quickly override the default format for displaying primitive types (the usual basic C/C++/ObjC types: int, float, char, ...).

+

LLDB has a list of formatting options available out of which you can pick:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Format nameAbbreviationDescription
defaultthe default LLDB algorithm is used to pick a format
booleanBshow this as a true/false boolean, using the customary rule that 0 is false and everything else is true
binarybshow this as a sequence of bits
bytesyshow the bytes one after the other
e.g. (int) s.x = 07 00 00 00
bytes with ASCIIYshow the bytes, but try to print them as ASCII characters
e.g. (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._....
charactercshow the bytes printed as ASCII characters
e.g. (int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0
printable characterCshow the bytes printed as printable ASCII characters
e.g. (int *) c.sp.x = P.._....
complex floatFinterpret this value as the real and imaginary part of a complex floating-point number
e.g. (int *) c.sp.x = 2.76658e+19 + 4.59163e-41i
c-stringsshow this as a 0-terminated C string
signed decimalishow this as a signed integer number (this does not perform a cast, it simply shows the bytes as signed integer)
enumerationEshow this as an enumeration, printing the value's name if available or the integer value otherwise
e.g. (enum enumType) val_type = eValue2
hexxshow this as in hexadecimal notation (this does not perform a cast, it simply shows the bytes as hex)
floatfshow this as a floating-point number (this does not perform a cast, it simply interprets the bytes as an IEEE754 floating-point value)
octaloshow this in octal notation
OSTypeOshow this as a MacOS OSType
e.g. (float) *c.sp.y = '\n\x1f\xd7\n'
unicode16Ushow this as UTF-16 characters
e.g. (float) *c.sp.y = 0xd70a 0x411f
unicode32show this as UTF-32 characters
e.g. (float) *c.sp.y = 0x411fd70a
unsigned decimalushow this as an unsigned integer number (this does not perform a cast, it simply shows the bytes as unsigned integer)
pointerpshow this as a native pointer (unless this is really a pointer, the resulting address will probably be invalid)
char[]show this as an array of characters
e.g. (char) *c.sp.z = {X}
int8_t[], uint8_t[]
int16_t[], uint16_t[]
int32_t[], uint32_t[]
int64_t[], uint64_t[]
uint128_t[]
show this as an array of the corresponding integer type
e.g.
(int) sarray[0].x = {1 0 0 0}
(int) sarray[0].x = {0x00000001}
float32[], float64[]show this as an array of the corresponding floating-point type
e.g. (int *) pointer = {1.46991e-39 1.4013e-45}
complex integerIinterpret this value as the real and imaginary part of a complex integer number
e.g. (int *) pointer = 1048960 + 1i
character arrayashow this as a character array
e.g. (int *) pointer = \x80\x01\x10\0\x01\0\0\0
+ +

Some of the examples shown are willingfully + unnatural ways to print some values, and meant to + show that there is no casting or data-loss occurring + when you change the format of a type. All that lldb + does when you ask it to change format is reinterpret + the bytes for display, leaving the original value + unaltered.

+ +

There are two ways to modify the format, one is + temporary and per-variable, the other is permanent + and per-type.

In the first case you can simply + use the -f option to frame + variable, passing it one of the format + names or abbreviations in the previous table:

+

frame variable counter -f hex

+

This has the effect of displaying the value of + counter as an hexadecimal number, and + will keep showing it this way until you either pick a + different format or a subsequent stoppoint is + hit.

Obviously, if you have two + int variables, and you format one as + hex, the other will be left untouched. If for some + reason, you want all int variables to + print out as hex, you must add a format to the + int type.

This is done by typing + type format add -f hex int at the LLDB + command line.

The -f option + accepts one of the format names or abbreviations, and + after that you can give out a list of names to which + you want the new format applied.

A frequent + scenario is that your program has a + typedef for a numeric type that you know + represents something that must be printed in a + certain way. Again, you can add a format just to that + typedef by using type format add with + the name alias.

But things can quickly get + hierarchical. Let's say you have a situation like the + following:

typedef int A;
typedef A + B;
typedef B C;
typedef C D;

+

and you want to show all As as hex, + all Cs as pointers and leave the + defaults untouched for other types.

If you + simply type
type format add -f hex + A
type format add -f pointer C

values + of type B will be shown as hex and + values of type D as pointers.

+

This is because by default LLDB cascades + formats through typedef chains. In order to avoid + that you can use the option -C no to + prevent cascading, thus making the two commands + required to achieve your goal:
type + format add -f hex -C no A
type format add -f + pointer -C no C

Two additional options + that you will want to look at are -p and + -r. These two options prevent LLDB from + applying a format for type T to values + of type T* and T& + respectively.

+

+ + (lldb) type format add -f float32[] int
+ (lldb) fr var pointer *pointer -T
+ (int *) pointer = {1.46991e-39 1.4013e-45}
+ (int) *pointer = {1.53302e-42}
+ (lldb) type format add -f float32[] int -p
+ (lldb) fr var pointer *pointer -T
+ (int *) pointer = 0x0000000100100180
+ (int) *pointer = {1.53302e-42}
+
+

+

As the previous example highlights, you will most + probably want to use -p for your + formats.

If you need to delete a custom format + simply type type format delete followed + by the name of the type to which the format applies. + To delete ALL formats, use type format + clear. To see all the formats defined, type + type format list.

+ +
+ +

type + summary

+ +

Type summaries enable you to add more information + to the default viewing format for a type, or to + completely replace it with your own display option. + Unlike formats which only apply to basic types, + summaries can be used on every type (basic types, + classes (C++ and Objective-C), arrays, ...).

+

The basic idea beneath type summaries is + extracting information from variables and arranging + it in a format that is suitable for display:

+ before adding a summary...
(lldb) + fr var -T one
(i_am_cool) one = {
(int) + integer = 3
(float) floating = 3.14159
+ (char) character = 'E'
+ }
+

after adding a summary...
+ (lldb) fr var one
(i_am_cool) one = int + = 3, float = 3.14159, char = 69

+ +

Evidently, somehow we managed to tell LLDB to grab + the three member variables of the + i_am_cool datatype, mix their values + with some text, and even ask it to display the + character member using a custom + format.

The way to do this is add a summary + string to the datatype using the type + summary add command.

Its syntax is + similar to type format add, but some + more options are supported that will be described in + the follow-up.

The main option to type + summary add is -f which accepts + as parameter a summary string. After that, you can + type as many type names as you want to associate the + given summary string to them.

+ +
+ +
+ +
+

Summary Strings

+
+ +

So what is the format of the summary strings? + Summary strings can contain plain text, control + characters and special symbols that have access to + information about the current object and the overall + program state.

+ +

Normal characters are any text that doesn't + contain a '{', + '}', '$', or + '\' character.

+ +

Variable names are found in between a + "${" prefix, and end with a + "}" suffix. In other words, a + variable looks like + "${frame.pc}".

+ +

Basically, all the variables described in Frame and Thread Formatting + are accepted. Also acceptable are the control + characters and scoping features described in that + page. Additionally, ${var and + ${*var become acceptable symbols in this + scenario.

The simplest thing you can do is + grab a member variable of a class or structure by + typing its expression path. In the previous + example, the expression path for the floating member + is simply .floating, because all you + have to do to get at it given an object of type + i_am_cool is access it straight away. + Thus, to ask the summary string to display + floating you would type + ${var.floating} (${var is a + placeholder token replaced with whatever variable is + being displayed).

If you have code like the + following:
struct A {
int x;
+ int y;
+ };
+ struct B {
A x;
A y;
int z;
+ };
+
the expression path for the y + member of the x member of an object of + type B would be .x.y and + you would type ${var.x.y} to display it + in a summary string for type B.

+

As you could be using a summary string for both + displaying objects of type T or + T* (unless -p is used to + prevent this), the expression paths do not + differentiate between . and + ->, and the above expression path + .x.y would be just as good if you were + displaying a B*, or even if the actual + definition of B were: +
+ struct B {
+ A *x;
+ A y;
+ int z;
+ };
+
+

+

This is unlike the behaviour of frame + variable which, on the contrary, will enforce + the distinction. As hinted above, the rationale for + this choice is that waiving this distinction enables + one to write a summary string once for type + T and use it for both T and + T* instances. As a summary string is + mostly about extracting nested members' information, + a pointer to an object is just as good as the object + itself for the purpose.

+ +

Of course, you can have multiple entries in one + summary string. For instance, the command used to + produce the above summary string for i_am_cool was: +
type summary add -f "int = ${var.integer}, + float = ${var.floating}, char = ${var.character%u}" + i_am_cool

As you can see, the last + expression path also contains a %u + symbol which is nowhere to be found in the actual + member variable name. The symbol is reminding of a + printf() format symbol, and in fact it + has a similar effect. If you add a % sign followed by + any one format name or abbreviation from the above + table after an expression path, the resulting object + will be displyed using exactly that format instead of + the LLDB default one. +

+

There are two more special format symbols that you + can use only as part of a summary string: + %V and %@. The first one + tells LLDB to ignore summary strings for the type of + the object referred by the expression path and + instead print the object's value. The second is only + applicable to Objective-C classes, and tells LLDB to + get the object's description from the Objective-C + runtime. By default, if no format is provided, LLDB + will try to get the object's summary, and if empty + the object's value. If neither can be obtained, + nothing will be displayed.

+

As previously said, pointers and values are + treated the same way when getting to their members in + an expression path. However, if your expression path + leads to a pointer, LLDB will not automatically + dereference it. In order to obtain The deferenced + value for a pointer, your expression path must start + with ${*var instead of + ${var. Because there is no need to + dereference pointers along your way, the + dereferencing symbol only applies to the result of + the whole expression path traversing. +
+ e.g. + +
+ (lldb) fr var -T c
+(Couple) c = {
+ (SimpleWithPointers) sp = {
+ (int *) x = 0x00000001001000b0
+ (float *) y = 0x00000001001000c0
+ (char *) z = 0x00000001001000d0 "X"
+ }
+ (Simple *) s = 0x00000001001000e0
+}
+(lldb) type summary add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = ${*var.s}" Couple
+(lldb) type summary add -c -p Simple
+(lldb) fr var c
+(Couple) c = int = 9, float = 9.99, char = 88, Simple = (x=9, y=9.99, z='X')
+
+

+

Option -c to type summary + add tells LLDB not to look for a summary + string, but instead to just print a listing of all + the object's children on one line, lay out as in the + previous example. The -p flag is used as + a trick to show that aggregate types can be + dereferenced as well as primitive ones. The above + output would be shown even by typing type + summary add -f "int = ${*var.sp.x}, float = + ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = + ${var.s}" Couple if one took away the + -p flag from the summary for type + Simple.

+ +
+ +
+ +
+

More on summary strings

+
+ +

What was described above are the main features + that you can use in summary strings. However, there + are three more features to them.

Sometimes, a + basic type's value actually represents several + different values packed together in a bitfield. With + the classical view, there is no way to look at them. + Hexadecimal display can help, but if the bits + actually span byte boundaries, the help is limited. + Binary view would show it all without ambiguity, but + is often too detailed and hard to read for real-life + scenarios. To cope with the issue, LLDB supports + native bitfield formatting in summary strings. If + your expression paths leads to a so-called scalar + type (the usual int, float, char, double, short, + long, long long, double, long double and unsigned + variants), you can ask LLDB to only grab some bits + out of the value and display them in any format you + like. The syntax is similar to that used for arrays, + just you can also give a pair of indices separated by + a -.
+ e.g. +
+ + (lldb) fr var float_point
+(float) float_point = -3.14159
+(lldb) type summary add -f "Sign: ${var[31]%B} Exponent: ${var[30-23]%x} Mantissa: ${var[0-22]%u}" float
+(lldb) fr var float_point
+(float) float_point = -3.14159 Sign: true Exponent: 0x00000080 Mantissa: 4788184
+
+ In this example, LLDB shows the internal + representation of a float variable by + extracting bitfields out of a float object. If you + give a single index, only that one bit will be + extracted. If you give a pair of indices, all the + bits in the range (extremes included) will be + extracted. Ranges can be specified either by giving + the lower index first, or higher index first (as is + often customary in describing packed data-type + formats).

+

The second additional feature allows you to + display array members inside a summary string. For + instance, you may want to display all arrays of a + given type using a more compact notation than the + default, and then just delve into individual array + members that prove interesting to your debugging + task. You can use a similar syntax to the one used + for bitfields to tell LLDB to format arrays in + special ways. +
+ e.g. +
+ + (lldb) fr var sarray
+(Simple [3]) sarray = {
+ [0] = {
+ x = 1
+ y = 2
+ z = '\x03'
+ }
+ [1] = {
+ x = 4
+ y = 5
+ z = '\x06'
+ }
+ [2] = {
+ x = 7
+ y = 8
+ z = '\t'
+ }
+}
+(lldb) type summary add -f "${var[].x}" "Simple [3]"
+(lldb) fr var sarray
+(Simple [3]) sarray = [1,4,7]
+
+ The [] symbol amounts to: if + var is an array and I knows its size, + apply this summary string to every element of the + array. Here, we are asking LLDB to display + .x for every element of the array, and + in fact this is what happens. If you find some of + those integers anomalous, you can then inspect that + one item in greater detail, without the array format + getting in the way: +
+ + (lldb) fr var sarray[1]
+(Simple) sarray[1] = {
+ x = 4
+ y = 5
+ z = '\x06'
+}
+
+

+

You can also ask LLDB to only print a subset of + the array range by using the same syntax used to + extract bit for bitfields.

The same logic + works if you are printing a pointer instead of an + array, however in this latter case, [] + cannot be used and you need to give exact range + limits.

The third, and last, additional + feature does not directly apply to the summary + strings themselves, but is an additional option to + the type summary add command: + -x

As you noticed, in order to + associate the custom summary string to the array + types, one must give the array size as part of the + typename. This can long become tiresome when using + arrays of different sizes, Simple [3], + Simple [9], Simple [12], + ...

If you use the -x option, + type names are treated as regular expressions instead + of type names. This would let you rephrase the above + example as: +
+ +(lldb) type summary add -f "${var[].x}" -x "Simple \[[0-9]+\]"
+(lldb) fr var sarray
+(Simple [3]) sarray = [1,4,7]
+
+ The above scenario works for Simple [3] + as well as for any other array of + Simple objects.

While this + feature is mostly useful for arrays, you could also + use regular expressions to catch other type sets + grouped by name. However, as regular expression + matching is slower than normal name matching, LLDB + will first try to match by name in any way it can, + and only when this fails, will it resort to regular + expression matching. Thus, if your type has a base + class with a cascading summary, this will be + preferred over any regular expression match for your + type itself.

+ +
+ +

Finding + summaries 101

+ +

While the rules for finding an appropriate + format for a type are relatively simple (just go + through typedef hierarchies), summaries follow a + more complicated process in finding the right + summary string for a variable. Namely, what + happens is:

  • If there is a summary for + the type of the variable, use it
  • If this + object is a pointer, and there is a summary for + the pointee type that does not skip pointers, use + it
  • If this object is a reference, and + there is a summary for the pointee type that does + not skip references, use it
  • If this + object is an Objective-C class with a parent + class, look at the parent class (and parent of + parent, ...)
  • If this object is a C++ + class with base classes, look at base classes (and + bases of bases, ...)
  • If this object is a + C++ class with virtual base classes, look at the + virtual base classes (and bases of bases, + ...)
  • If this object's type is a typedef, + go through typedef hierarchy
  • If + everything has failed, repeat the above search, + looking for regular expressions instead of exact + matches
+ +

TODOs

+
+ +
  • There's no way to do multiple dereferencing, + and you need to be careful what the dereferencing + operation is binding to in complicated scenarios
  • +
  • There is no way to call functions inside summary + strings, not even const ones
  • +
  • type format add does not support the + -x option
  • Object location cannot + be printed in the summary string
+
+ +
+ +
+
+
+ + \ No newline at end of file Propchange: lldb/trunk/www/varformats.html ------------------------------------------------------------------------------ svn:executable = * From gclayton at apple.com Wed Jul 6 20:59:52 2011 From: gclayton at apple.com (Greg Clayton) Date: Thu, 07 Jul 2011 01:59:52 -0000 Subject: [Lldb-commits] [lldb] r134579 - in /lldb/trunk: include/lldb/Core/ include/lldb/Interpreter/ include/lldb/Symbol/ include/lldb/Target/ lldb.xcodeproj/xcshareddata/xcschemes/ source/Commands/ source/Core/ source/Expression/ source/Interpreter/ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/ source/Plugins/Process/gdb-remote/ source/Plugins/SymbolFile/DWARF/ source/Symbol/ source/Target/ tools/lldb-platform/ Message-ID: <20110707015952.D79492A6C12C@llvm.org> Author: gclayton Date: Wed Jul 6 20:59:51 2011 New Revision: 134579 URL: http://llvm.org/viewvc/llvm-project?rev=134579&view=rev Log: Added "target variable" command that allows introspection of global variables prior to running your binary. Zero filled sections now get section data correctly filled with zeroes when Target::ReadMemory reads from the object file section data. Added new option groups and option values for file lists. I still need to hook up all of the options to "target variable" to allow more complete introspection by file and shlib. Added the ability for ValueObjectVariable objects to be created with only the target as the execution context. This allows them to be read from the object files through Target::ReadMemory(...). Added a "virtual Module * GetModule()" function to the ValueObject class. By default it will look to the parent variable object and return its module. The module is needed when we have global variables that have file addresses (virtual addresses that are specific to module object files) and in turn allows global variables to be displayed prior to running. Removed all of the unused proxy object support that bit rotted in lldb_private::Value. Replaced a lot of places that used "FileSpec::Compare (lhs, rhs) == 0" code with the more efficient "FileSpec::Equal (lhs, rhs)". Improved logging in GDB remote plug-in. Modified: lldb/trunk/include/lldb/Core/FileSpecList.h lldb/trunk/include/lldb/Core/Module.h lldb/trunk/include/lldb/Core/ModuleList.h lldb/trunk/include/lldb/Core/Value.h lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Core/ValueObjectMemory.h lldb/trunk/include/lldb/Core/ValueObjectVariable.h lldb/trunk/include/lldb/Interpreter/NamedOptionValue.h lldb/trunk/include/lldb/Interpreter/OptionGroupFile.h lldb/trunk/include/lldb/Symbol/Variable.h lldb/trunk/include/lldb/Target/ExecutionContext.h lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme lldb/trunk/source/Commands/CommandObjectMemory.cpp lldb/trunk/source/Commands/CommandObjectTarget.cpp lldb/trunk/source/Core/Broadcaster.cpp lldb/trunk/source/Core/Communication.cpp lldb/trunk/source/Core/FileSpecList.cpp lldb/trunk/source/Core/Module.cpp lldb/trunk/source/Core/ModuleList.cpp lldb/trunk/source/Core/SearchFilter.cpp lldb/trunk/source/Core/Section.cpp lldb/trunk/source/Core/SourceManager.cpp lldb/trunk/source/Core/Value.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Core/ValueObjectChild.cpp lldb/trunk/source/Core/ValueObjectDynamicValue.cpp lldb/trunk/source/Core/ValueObjectMemory.cpp lldb/trunk/source/Core/ValueObjectVariable.cpp lldb/trunk/source/Expression/DWARFExpression.cpp lldb/trunk/source/Interpreter/NamedOptionValue.cpp lldb/trunk/source/Interpreter/OptionGroupFile.cpp lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Symbol/CompileUnit.cpp lldb/trunk/source/Target/ExecutionContext.cpp lldb/trunk/source/Target/Target.cpp lldb/trunk/tools/lldb-platform/lldb-platform.cpp Modified: lldb/trunk/include/lldb/Core/FileSpecList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/FileSpecList.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/FileSpecList.h (original) +++ lldb/trunk/include/lldb/Core/FileSpecList.h Wed Jul 6 20:59:51 2011 @@ -102,7 +102,7 @@ /// The stream that will be used to dump the object description. //------------------------------------------------------------------ void - Dump (Stream *s) const; + Dump (Stream *s, const char *separator_cstr = "\n") const; //------------------------------------------------------------------ /// Find a file index. Modified: lldb/trunk/include/lldb/Core/Module.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Module.h (original) +++ lldb/trunk/include/lldb/Core/Module.h Wed Jul 6 20:59:51 2011 @@ -157,6 +157,33 @@ SymbolContextList &sc_list); //------------------------------------------------------------------ + /// Find compile units by partial or full path. + /// + /// Finds all compile units that match \a path in all of the modules + /// and returns the results in \a sc_list. + /// + /// @param[in] path + /// The name of the function we are looking for. + /// + /// @param[in] append + /// If \b true, then append any compile units that were found + /// to \a sc_list. If \b false, then the \a sc_list is cleared + /// and the contents of \a sc_list are replaced. + /// + /// @param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// + /// @return + /// The number of matches added to \a sc_list. + //------------------------------------------------------------------ + uint32_t + FindCompileUnits (const FileSpec &path, + bool append, + SymbolContextList &sc_list); + + + //------------------------------------------------------------------ /// Find functions by name. /// /// @param[in] name Modified: lldb/trunk/include/lldb/Core/ModuleList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ModuleList.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ModuleList.h (original) +++ lldb/trunk/include/lldb/Core/ModuleList.h Wed Jul 6 20:59:51 2011 @@ -140,6 +140,32 @@ GetModulePointerAtIndex (uint32_t idx) const; //------------------------------------------------------------------ + /// Find compile units by partial or full path. + /// + /// Finds all compile units that match \a path in all of the modules + /// and returns the results in \a sc_list. + /// + /// @param[in] path + /// The name of the function we are looking for. + /// + /// @param[in] append + /// If \b true, then append any compile units that were found + /// to \a sc_list. If \b false, then the \a sc_list is cleared + /// and the contents of \a sc_list are replaced. + /// + /// @param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// + /// @return + /// The number of matches added to \a sc_list. + //------------------------------------------------------------------ + uint32_t + FindCompileUnits (const FileSpec &path, + bool append, + SymbolContextList &sc_list); + + //------------------------------------------------------------------ /// Find functions by name. /// /// Finds all functions that match \a name in all of the modules and @@ -161,7 +187,7 @@ /// @return /// The number of matches added to \a sc_list. //------------------------------------------------------------------ - size_t + uint32_t FindFunctions (const ConstString &name, uint32_t name_type_mask, bool include_symbols, Modified: lldb/trunk/include/lldb/Core/Value.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Value.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Value.h (original) +++ lldb/trunk/include/lldb/Core/Value.h Wed Jul 6 20:59:51 2011 @@ -48,32 +48,16 @@ eContextTypeRegisterInfo, // RegisterInfo * eContextTypeLLDBType, // lldb_private::Type * eContextTypeVariable, // lldb_private::Variable * - eContextTypeValue // Value * (making this a proxy value. Used when putting locals on the DWARF expression parser stack) }; Value(); Value(const Scalar& scalar); - Value(int v); - Value(unsigned int v); - Value(long v); - Value(unsigned long v); - Value(long long v); - Value(unsigned long long v); - Value(float v); - Value(double v); - Value(long double v); Value(const uint8_t *bytes, int len); Value(const Value &rhs); Value & operator=(const Value &rhs); - Value * - CreateProxy(); - - Value * - GetProxyTarget(); - lldb::clang_type_t GetClangType(); @@ -84,16 +68,30 @@ GetValueAddressType () const; ContextType - GetContextType() const; + GetContextType() const + { + return m_context_type; + } void - SetValueType (ValueType value_type); + SetValueType (ValueType value_type) + { + m_value_type = value_type; + } void - ClearContext (); + ClearContext () + { + m_context = NULL; + m_context_type = eContextTypeInvalid; + } void - SetContext (ContextType context_type, void *p); + SetContext (ContextType context_type, void *p) + { + m_context_type = context_type; + m_context = p; + } RegisterInfo * GetRegisterInfo(); @@ -105,7 +103,10 @@ ResolveValue (ExecutionContext *exe_ctx, clang::ASTContext *ast_context); Scalar & - GetScalar(); + GetScalar() + { + return m_value; + } void ResizeData(int len); @@ -126,7 +127,11 @@ GetValueByteSize (clang::ASTContext *ast_context, Error *error_ptr); Error - GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context, DataExtractor &data, uint32_t data_offset); + GetValueAsData (ExecutionContext *exe_ctx, + clang::ASTContext *ast_context, + DataExtractor &data, + uint32_t data_offset, + Module *module); // Can be NULL static const char * GetValueTypeAsCString (ValueType context_type); Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Wed Jul 6 20:59:51 2011 @@ -322,6 +322,16 @@ virtual bool SetValueFromCString (const char *value_str); + // Return the module associated with this value object in case the + // value is from an executable file and might have its data in + // sections of the file. This can be used for variables. + virtual Module * + GetModule() + { + if (m_parent) + return m_parent->GetModule(); + return NULL; + } //------------------------------------------------------------------ // The functions below should NOT be modified by sublasses //------------------------------------------------------------------ Modified: lldb/trunk/include/lldb/Core/ValueObjectMemory.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectMemory.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObjectMemory.h (original) +++ lldb/trunk/include/lldb/Core/ValueObjectMemory.h Wed Jul 6 20:59:51 2011 @@ -62,6 +62,9 @@ virtual bool IsInScope (); + virtual Module* + GetModule(); + protected: virtual bool UpdateValue (); Modified: lldb/trunk/include/lldb/Core/ValueObjectVariable.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectVariable.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObjectVariable.h (original) +++ lldb/trunk/include/lldb/Core/ValueObjectVariable.h Wed Jul 6 20:59:51 2011 @@ -52,6 +52,9 @@ virtual bool IsInScope (); + virtual Module* + GetModule(); + protected: virtual bool UpdateValue (); Modified: lldb/trunk/include/lldb/Interpreter/NamedOptionValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/NamedOptionValue.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/NamedOptionValue.h (original) +++ lldb/trunk/include/lldb/Interpreter/NamedOptionValue.h Wed Jul 6 20:59:51 2011 @@ -19,6 +19,7 @@ // Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/UUID.h" +#include "lldb/Core/FileSpecList.h" #include "lldb/Host/FileSpec.h" namespace lldb_private { @@ -28,6 +29,7 @@ class OptionValueUInt64; class OptionValueString; class OptionValueFileSpec; + class OptionValueFileSpecList; class OptionValueFormat; class OptionValueUUID; class OptionValueArray; @@ -46,6 +48,7 @@ eTypeDictionary, eTypeEnum, eTypeFileSpec, + eTypeFileSpecList, eTypeFormat, eTypeSInt64, eTypeUInt64, @@ -108,6 +111,9 @@ OptionValueFileSpec * GetAsFileSpec (); + OptionValueFileSpecList * + GetAsFileSpecList (); + OptionValueFormat * GetAsFormat (); @@ -644,7 +650,79 @@ FileSpec m_current_value; FileSpec m_default_value; }; - + + //--------------------------------------------------------------------- + // OptionValueFileSpecList + //--------------------------------------------------------------------- + class OptionValueFileSpecList : public OptionValue + { + public: + OptionValueFileSpecList () : + m_current_value () + { + } + + OptionValueFileSpecList (const FileSpecList ¤t_value) : + m_current_value (current_value) + { + } + + + virtual + ~OptionValueFileSpecList() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () + { + return eTypeFileSpecList; + } + + virtual void + DumpValue (Stream &strm); + + virtual Error + SetValueFromCString (const char *value); + + virtual bool + Clear () + { + m_current_value.Clear(); + m_value_was_set = false; + return true; + } + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + FileSpecList & + GetCurrentValue() + { + return m_current_value; + } + + const FileSpecList & + GetCurrentValue() const + { + return m_current_value; + } + + void + SetCurrentValue (const FileSpecList &value) + { + m_current_value = value; + } + + protected: + FileSpecList m_current_value; + }; + //--------------------------------------------------------------------- // OptionValueFormat //--------------------------------------------------------------------- Modified: lldb/trunk/include/lldb/Interpreter/OptionGroupFile.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionGroupFile.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/OptionGroupFile.h (original) +++ lldb/trunk/include/lldb/Interpreter/OptionGroupFile.h Wed Jul 6 20:59:51 2011 @@ -18,6 +18,7 @@ #include "lldb/Interpreter/NamedOptionValue.h" namespace lldb_private { + //------------------------------------------------------------------------- // OptionGroupFile //------------------------------------------------------------------------- @@ -76,6 +77,65 @@ }; +//------------------------------------------------------------------------- +// OptionGroupFileList +//------------------------------------------------------------------------- + +class OptionGroupFileList : public OptionGroup +{ +public: + + OptionGroupFileList (uint32_t usage_mask, + bool required, + const char *long_option, + char short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text); + + virtual + ~OptionGroupFileList (); + + + virtual uint32_t + GetNumDefinitions () + { + return 1; + } + + virtual const OptionDefinition* + GetDefinitions () + { + return &m_option_definition; + } + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + + OptionValueFileSpecList & + GetOptionValue () + { + return m_file_list; + } + + const OptionValueFileSpecList & + GetOptionValue () const + { + return m_file_list; + } + +protected: + OptionValueFileSpecList m_file_list; + OptionDefinition m_option_definition; + +}; + } // namespace lldb_private #endif // liblldb_OptionGroupFile_h_ Modified: lldb/trunk/include/lldb/Symbol/Variable.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Variable.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/Variable.h (original) +++ lldb/trunk/include/lldb/Symbol/Variable.h Wed Jul 6 20:59:51 2011 @@ -53,6 +53,12 @@ const ConstString& GetName() const; + SymbolContextScope * + GetSymbolContextScope() const + { + return m_owner_scope; + } + // Since a variable can have a basename "i" and also a mangled // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name // "(anonymous namespace)::i", this function will allow a generic match Modified: lldb/trunk/include/lldb/Target/ExecutionContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ExecutionContext.h?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/ExecutionContext.h (original) +++ lldb/trunk/include/lldb/Target/ExecutionContext.h Wed Jul 6 20:59:51 2011 @@ -80,6 +80,9 @@ ExecutionContextScope * GetBestExecutionContextScope () const; + Process * + GetProcess () const; + //------------------------------------------------------------------ // Member variables //------------------------------------------------------------------ Modified: lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme (original) +++ lldb/trunk/lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme Wed Jul 6 20:59:51 2011 @@ -89,6 +89,16 @@ ReferencedContainer = "container:lldb.xcodeproj"> + + + + + + 0) + { + for (size_t idx = 0; idx < argc; ++idx) + { + VariableList global_var_list; + const char *global_var_name = args.GetArgumentAtIndex(idx); + const uint32_t matches = exe_ctx.target->GetImages().FindGlobalVariables (global_var_name, + true, + UINT32_MAX, + global_var_list); + + if (matches == 0) + { + result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", + global_var_name); + } + else + { + for (uint32_t global_idx=0; global_idxSetFormat (format); + +// if (m_format_options.show_decl && var_sp->GetDeclaration ().GetFile()) +// { +// var_sp->GetDeclaration ().DumpStopContext (&s, false); +// s.PutCString (": "); +// } + + ValueObject::DumpValueObject (result.GetOutputStream(), + valobj_sp.get(), + global_var_name, + m_varobj_options.ptr_depth, + 0, + m_varobj_options.max_depth, + m_varobj_options.show_types, + m_varobj_options.show_location, + m_varobj_options.use_objc, + m_varobj_options.use_dynamic, + false, + m_varobj_options.flat_output); + } + } + } + } + } + } + else + { + result.AppendError ("'target variable' takes one or more global variable names as arguments\n"); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendError ("invalid target, create a debug target using the 'target create' command"); + result.SetStatus (eReturnStatusFailed); + return false; + } + return result.Succeeded(); + } + + Options * + GetOptions () + { + return &m_option_group; + } + +protected: + OptionGroupOptions m_option_group; + OptionGroupFormat m_format_options; + OptionGroupFileList m_option_compile_units; + OptionGroupFileList m_option_shared_libraries; + OptionGroupValueObjectDisplay m_varobj_options; + +}; + + #pragma mark CommandObjectTargetModulesSearchPathsAdd class CommandObjectTargetModulesSearchPathsAdd : public CommandObject @@ -1137,14 +1268,11 @@ } static uint32_t -LookupTypeInModule -( - CommandInterpreter &interpreter, - Stream &strm, - Module *module, - const char *name_cstr, - bool name_is_regex - ) +LookupTypeInModule (CommandInterpreter &interpreter, + Stream &strm, + Module *module, + const char *name_cstr, + bool name_is_regex) { if (module && name_cstr && name_cstr[0]) { @@ -3565,6 +3693,7 @@ LoadSubCommand ("select", CommandObjectSP (new CommandObjectTargetSelect (interpreter))); LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter))); LoadSubCommand ("modules", CommandObjectSP (new CommandObjectTargetModules (interpreter))); + LoadSubCommand ("variable", CommandObjectSP (new CommandObjectTargetVariable (interpreter))); } CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget () Modified: lldb/trunk/source/Core/Broadcaster.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Broadcaster.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/Broadcaster.cpp (original) +++ lldb/trunk/source/Core/Broadcaster.cpp Wed Jul 6 20:59:51 2011 @@ -239,13 +239,6 @@ if (hijacking_listener) { - // FIXME: REMOVE THIS EXTRA LOGGING - LogSP log_process(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log_process) - log_process->Printf ("Hijacking event delivery for Broadcaster(\"%s\") to Listener(\"%s\").", - m_broadcaster_name.AsCString(""), - hijacking_listener->GetName()); - if (unique && hijacking_listener->PeekAtNextEventForBroadcasterWithType (this, event_type)) return; hijacking_listener->AddEvent (event_sp); Modified: lldb/trunk/source/Core/Communication.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Communication.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/Communication.cpp (original) +++ lldb/trunk/source/Core/Communication.cpp Wed Jul 6 20:59:51 2011 @@ -368,7 +368,10 @@ case eConnectionStatusError: // Check GetError() for details case eConnectionStatusTimedOut: // Request timed out if (log) - error.LogIfError(log.get(), "%p Communication::ReadFromConnection () => status = %i", p, status); + error.LogIfError(log.get(), + "%p Communication::ReadFromConnection () => status = %s", + p, + Communication::ConnectionStatusAsCString (status)); break; } } Modified: lldb/trunk/source/Core/FileSpecList.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FileSpecList.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/FileSpecList.cpp (original) +++ lldb/trunk/source/Core/FileSpecList.cpp Wed Jul 6 20:59:51 2011 @@ -88,9 +88,15 @@ // Dumps the file list to the supplied stream pointer "s". //------------------------------------------------------------------ void -FileSpecList::Dump(Stream *s) const +FileSpecList::Dump(Stream *s, const char *separator_cstr) const { - for_each (m_files.begin(), m_files.end(), bind2nd(mem_fun_ref(&FileSpec::Dump),s)); + collection::const_iterator pos, end = m_files.end(); + for (pos = m_files.begin(); pos != end; ++pos) + { + pos->Dump(s); + if (separator_cstr) + s->PutCString(separator_cstr); + } } //------------------------------------------------------------------ Modified: lldb/trunk/source/Core/Module.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/Module.cpp (original) +++ lldb/trunk/source/Core/Module.cpp Wed Jul 6 20:59:51 2011 @@ -193,16 +193,6 @@ return cu_sp; } -//CompUnitSP -//Module::FindCompUnit(lldb::user_id_t uid) -//{ -// CompUnitSP cu_sp; -// SymbolVendor *symbols = GetSymbolVendor (); -// if (symbols) -// cu_sp = symbols->FindCompUnit(uid); -// return cu_sp; -//} - bool Module::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) { @@ -323,6 +313,28 @@ } uint32_t +Module::FindCompileUnits (const FileSpec &path, + bool append, + SymbolContextList &sc_list) +{ + if (!append) + sc_list.Clear(); + + const uint32_t start_size = sc_list.GetSize(); + const uint32_t num_compile_units = GetNumCompileUnits(); + SymbolContext sc; + sc.module_sp = GetSP(); + const bool compare_directory = path.GetDirectory(); + for (uint32_t i=0; iFindCompileUnits (path, true, sc_list); + } + + return sc_list.GetSize(); +} + +uint32_t ModuleList::FindGlobalVariables (const ConstString &name, bool append, uint32_t max_matches, Modified: lldb/trunk/source/Core/SearchFilter.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/SearchFilter.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/SearchFilter.cpp (original) +++ lldb/trunk/source/Core/SearchFilter.cpp Wed Jul 6 20:59:51 2011 @@ -326,7 +326,7 @@ bool SearchFilterByModule::ModulePasses (const ModuleSP &module_sp) { - if (module_sp && FileSpec::Compare (module_sp->GetFileSpec(), m_module_spec, false) == 0) + if (module_sp && FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false)) return true; else return false; Modified: lldb/trunk/source/Core/Section.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Section.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/Section.cpp (original) +++ lldb/trunk/source/Core/Section.cpp Wed Jul 6 20:59:51 2011 @@ -331,8 +331,25 @@ if (file) { - off_t section_file_offset = GetFileOffset() + objfile->GetOffset() + section_offset; - return file.ReadFileContents (section_file_offset, dst, dst_len); + size_t bytes_left = dst_len; + size_t bytes_read = 0; + const uint64_t file_size = GetFileSize(); + if (section_offset < file_size) + { + off_t section_file_offset = objfile->GetOffset() + GetFileOffset() + section_offset; + bytes_read = file.ReadFileContents (section_file_offset, dst, dst_len); + if (bytes_read >= dst_len) + return bytes_read; + bytes_left -= bytes_read; + } + + const uint64_t byte_size = GetByteSize(); + if (section_offset + bytes_read < byte_size) + { + memset ((uint8_t*)dst + bytes_read, 0, bytes_left); + bytes_read += bytes_left; + } + return bytes_read; } } return 0; Modified: lldb/trunk/source/Core/SourceManager.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/SourceManager.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/SourceManager.cpp (original) +++ lldb/trunk/source/Core/SourceManager.cpp Wed Jul 6 20:59:51 2011 @@ -279,7 +279,7 @@ bool SourceManager::File::FileSpecMatches (const FileSpec &file_spec) { - return FileSpec::Compare (m_file_spec, file_spec, false) == 0; + return FileSpec::Equal (m_file_spec, file_spec, false); } Modified: lldb/trunk/source/Core/Value.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Value.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/Value.cpp (original) +++ lldb/trunk/source/Core/Value.cpp Wed Jul 6 20:59:51 2011 @@ -31,98 +31,30 @@ using namespace lldb_private; Value::Value() : - m_value(), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) + m_value (), + m_value_type (eValueTypeScalar), + m_context (NULL), + m_context_type (eContextTypeInvalid), + m_data_buffer () { } Value::Value(const Scalar& scalar) : - m_value(scalar), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) + m_value (scalar), + m_value_type (eValueTypeScalar), + m_context (NULL), + m_context_type (eContextTypeInvalid), + m_data_buffer () { } -Value::Value(int v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(unsigned int v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(long v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(unsigned long v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(long long v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(unsigned long long v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(float v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(double v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} - -Value::Value(long double v) : - m_value(v), - m_value_type(eValueTypeScalar), - m_context(NULL), - m_context_type(eContextTypeInvalid) -{ -} Value::Value(const uint8_t *bytes, int len) : - m_value(), - m_value_type(eValueTypeHostAddress), - m_context(NULL), - m_context_type(eContextTypeInvalid) + m_value (), + m_value_type (eValueTypeHostAddress), + m_context (NULL), + m_context_type (eContextTypeInvalid), + m_data_buffer () { m_data_buffer.CopyData(bytes, len); m_value = (uintptr_t)m_data_buffer.GetBytes(); @@ -163,35 +95,9 @@ return *this; } -Value * -Value::CreateProxy() -{ - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->CreateProxy (); - - Value *ret = new Value; - ret->SetContext(eContextTypeValue, this); - return ret; -} - -Value * -Value::GetProxyTarget() -{ - if (m_context_type == eContextTypeValue) - return (Value*)m_context; - else - return NULL; -} - void Value::Dump (Stream* strm) { - if (m_context_type == eContextTypeValue) - { - ((Value*)m_context)->Dump (strm); - return; - } - m_value.GetValue (strm, true); strm->Printf(", value_type = %s, context = %p, context_type = %s", Value::GetValueTypeAsCString(m_value_type), @@ -202,18 +108,12 @@ Value::ValueType Value::GetValueType() const { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetValueType (); - return m_value_type; } AddressType Value::GetValueAddressType () const { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetValueAddressType (); - switch (m_value_type) { default: @@ -226,60 +126,9 @@ return eAddressTypeInvalid; } - -Value::ContextType -Value::GetContextType() const -{ - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetContextType (); - - return m_context_type; -} - -void -Value::SetValueType (Value::ValueType value_type) -{ - if (m_context_type == eContextTypeValue) - { - ((Value*)m_context)->SetValueType(value_type); - return; - } - - m_value_type = value_type; -} - -void -Value::ClearContext () -{ - if (m_context_type == eContextTypeValue) - { - ((Value*)m_context)->ClearContext(); - return; - } - - m_context = NULL; - m_context_type = eContextTypeInvalid; -} - -void -Value::SetContext (Value::ContextType context_type, void *p) -{ - if (m_context_type == eContextTypeValue) - { - ((Value*)m_context)->SetContext(context_type, p); - return; - } - - m_context_type = context_type; - m_context = p; -} - RegisterInfo * Value::GetRegisterInfo() { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetRegisterInfo(); - if (m_context_type == eContextTypeRegisterInfo) return static_cast (m_context); return NULL; @@ -288,32 +137,14 @@ Type * Value::GetType() { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetType(); - if (m_context_type == eContextTypeLLDBType) return static_cast (m_context); return NULL; } -Scalar & -Value::GetScalar() -{ - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetScalar(); - - return m_value; -} - void Value::ResizeData(int len) { - if (m_context_type == eContextTypeValue) - { - ((Value*)m_context)->ResizeData(len); - return; - } - m_value_type = eValueTypeHostAddress; m_data_buffer.SetByteSize(len); m_value = (uintptr_t)m_data_buffer.GetBytes(); @@ -322,19 +153,16 @@ bool Value::ValueOf(ExecutionContext *exe_ctx, clang::ASTContext *ast_context) { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->ValueOf(exe_ctx, ast_context); - switch (m_context_type) { default: case eContextTypeInvalid: - case eContextTypeClangType: // clang::Type * - case eContextTypeRegisterInfo: // RegisterInfo * - case eContextTypeLLDBType: // Type * + case eContextTypeClangType: // clang::Type * + case eContextTypeRegisterInfo: // RegisterInfo * + case eContextTypeLLDBType: // Type * break; - case eContextTypeVariable: // Variable * + case eContextTypeVariable: // Variable * ResolveValue(exe_ctx, ast_context); return true; } @@ -344,9 +172,6 @@ size_t Value::GetValueByteSize (clang::ASTContext *ast_context, Error *error_ptr) { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetValueByteSize(ast_context, error_ptr); - size_t byte_size = 0; switch (m_context_type) @@ -412,9 +237,6 @@ clang_type_t Value::GetClangType () { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetClangType(); - switch (m_context_type) { default: @@ -444,9 +266,6 @@ lldb::Format Value::GetValueDefaultFormat () { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetValueDefaultFormat(); - switch (m_context_type) { default: @@ -506,11 +325,12 @@ } Error -Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context, DataExtractor &data, uint32_t data_offset) +Value::GetValueAsData (ExecutionContext *exe_ctx, + clang::ASTContext *ast_context, + DataExtractor &data, + uint32_t data_offset, + Module *module) { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetValueAsData(exe_ctx, ast_context, data, data_offset); - data.Clear(); Error error; @@ -544,16 +364,20 @@ { error.SetErrorString ("can't read load address (no execution context)"); } - else if (exe_ctx->process == NULL) + else { - error.SetErrorString ("can't read load address (invalid process)"); - } - else - { - address = m_value.ULongLong(LLDB_INVALID_ADDRESS); - address_type = eAddressTypeLoad; - data.SetByteOrder(exe_ctx->process->GetTarget().GetArchitecture().GetByteOrder()); - data.SetAddressByteSize(exe_ctx->process->GetTarget().GetArchitecture().GetAddressByteSize()); + Process *process = exe_ctx->GetProcess(); + if (process == NULL) + { + error.SetErrorString ("can't read load address (invalid process)"); + } + else + { + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + address_type = eAddressTypeLoad; + data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder()); + data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize()); + } } break; @@ -568,71 +392,91 @@ } else { - // The only thing we can currently lock down to a module so that - // we can resolve a file address, is a variable. - Variable *variable = GetVariable(); - - if (GetVariable()) + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + if (address == LLDB_INVALID_ADDRESS) { - address = m_value.ULongLong(LLDB_INVALID_ADDRESS); - if (address != LLDB_INVALID_ADDRESS) + error.SetErrorString ("invalid file address"); + } + else + { + if (module == NULL) + { + // The only thing we can currently lock down to a module so that + // we can resolve a file address, is a variable. + Variable *variable = GetVariable(); + if (variable) + { + SymbolContext var_sc; + variable->CalculateSymbolContext(&var_sc); + module = var_sc.module_sp.get(); + } + } + + if (module) { bool resolved = false; - SymbolContext var_sc; - variable->CalculateSymbolContext(&var_sc); - if (var_sc.module_sp) + ObjectFile *objfile = module->GetObjectFile(); + if (objfile) { - ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); - if (objfile) + Address so_addr(address, objfile->GetSectionList()); + addr_t load_address = so_addr.GetLoadAddress (exe_ctx->target); + if (load_address != LLDB_INVALID_ADDRESS) { - Address so_addr(address, objfile->GetSectionList()); - addr_t load_address = so_addr.GetLoadAddress (exe_ctx->target); - if (load_address != LLDB_INVALID_ADDRESS) + resolved = true; + address = load_address; + address_type = eAddressTypeLoad; + data.SetByteOrder(exe_ctx->target->GetArchitecture().GetByteOrder()); + data.SetAddressByteSize(exe_ctx->target->GetArchitecture().GetAddressByteSize()); + } + else + { + if (so_addr.IsSectionOffset()) { resolved = true; - address = load_address; - address_type = eAddressTypeLoad; - data.SetByteOrder(exe_ctx->target->GetArchitecture().GetByteOrder()); - data.SetAddressByteSize(exe_ctx->target->GetArchitecture().GetAddressByteSize()); - } - else - { - if (so_addr.IsSectionOffset()) - { - resolved = true; - file_so_addr = so_addr; - data.SetByteOrder(objfile->GetByteOrder()); - data.SetAddressByteSize(objfile->GetAddressByteSize()); - } + file_so_addr = so_addr; + data.SetByteOrder(objfile->GetByteOrder()); + data.SetAddressByteSize(objfile->GetAddressByteSize()); } } } if (!resolved) { - if (var_sc.module_sp) - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", - address, - variable->GetName().AsCString(""), - var_sc.module_sp->GetFileSpec().GetDirectory().GetCString(), - var_sc.module_sp->GetFileSpec().GetDirectory() ? "/" : "", - var_sc.module_sp->GetFileSpec().GetFilename().GetCString()); + Variable *variable = GetVariable(); + + if (module) + { + if (variable) + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", + address, + variable->GetName().AsCString(""), + module->GetFileSpec().GetDirectory().GetCString(), + module->GetFileSpec().GetDirectory() ? "/" : "", + module->GetFileSpec().GetFilename().GetCString()); + else + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx in %s%s%s", + address, + module->GetFileSpec().GetDirectory().GetCString(), + module->GetFileSpec().GetDirectory() ? "/" : "", + module->GetFileSpec().GetFilename().GetCString()); + } else - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", - address, - variable->GetName().AsCString("")); + { + if (variable) + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", + address, + variable->GetName().AsCString("")); + else + error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx", address); + } } } else { - error.SetErrorString ("invalid file address"); + // Can't convert a file address to anything valid without more + // context (which Module it came from) + error.SetErrorString ("can't read memory from file address without more context"); } } - else - { - // Can't convert a file address to anything valid without more - // context (which Module it came from) - error.SetErrorString ("can't read memory from file address without more context"); - } } break; @@ -695,9 +539,24 @@ } else { - if (exe_ctx->process->ReadMemory(address, dst, byte_size, error) != byte_size) + // The execution context might have a NULL process, but it + // might have a valid process in the exe_ctx->target, so use + // the ExecutionContext::GetProcess accessor to ensure we + // get the process if there is one. + Process *process = exe_ctx->GetProcess(); + + if (process) { - error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address); + const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error); + if (bytes_read != byte_size) + error.SetErrorStringWithFormat("read memory from 0x%llx failed (%u of %u bytes read)", + (uint64_t)address, + (uint32_t)bytes_read, + (uint32_t)byte_size); + } + else + { + error.SetErrorStringWithFormat("read memory from 0x%llx failed (invalid process)", (uint64_t)address); } } } @@ -717,30 +576,9 @@ Scalar & Value::ResolveValue(ExecutionContext *exe_ctx, clang::ASTContext *ast_context) { - Scalar scalar; - if (m_context_type == eContextTypeValue) + void *opaque_clang_qual_type = GetClangType(); + if (opaque_clang_qual_type) { - // Resolve the proxy - - Value * rhs = (Value*)m_context; - - m_value = rhs->m_value; - m_value_type = rhs->m_value_type; - m_context = rhs->m_context; - m_context_type = rhs->m_context_type; - - if ((uintptr_t)rhs->m_value.ULongLong(LLDB_INVALID_ADDRESS) == (uintptr_t)rhs->m_data_buffer.GetBytes()) - { - m_data_buffer.CopyData(rhs->m_data_buffer.GetBytes(), - rhs->m_data_buffer.GetByteSize()); - - m_value = (uintptr_t)m_data_buffer.GetBytes(); - } - } - - if (m_context_type == eContextTypeClangType) - { - void *opaque_clang_qual_type = GetClangType(); switch (m_value_type) { case eValueTypeScalar: // raw scalar value @@ -759,6 +597,7 @@ DataExtractor data; if (ClangASTType::ReadFromMemory (ast_context, opaque_clang_qual_type, exe_ctx, addr, address_type, data)) { + Scalar scalar; if (ClangASTType::GetValueAsScalar (ast_context, opaque_clang_qual_type, data, 0, data.GetByteSize(), scalar)) { m_value = scalar; @@ -784,8 +623,6 @@ } break; } - - } return m_value; } @@ -793,16 +630,11 @@ Variable * Value::GetVariable() { - if (m_context_type == eContextTypeValue) - return ((Value*)m_context)->GetVariable(); - if (m_context_type == eContextTypeVariable) return static_cast (m_context); return NULL; } - - const char * Value::GetValueTypeAsCString (ValueType value_type) { @@ -821,12 +653,11 @@ { switch (context_type) { - case eContextTypeInvalid: return "invalid"; - case eContextTypeClangType: return "clang::Type *"; - case eContextTypeRegisterInfo: return "RegisterInfo *"; - case eContextTypeLLDBType: return "Type *"; - case eContextTypeVariable: return "Variable *"; - case eContextTypeValue: return "Value"; // TODO: Sean, more description here? + case eContextTypeInvalid: return "invalid"; + case eContextTypeClangType: return "clang::Type *"; + case eContextTypeRegisterInfo: return "RegisterInfo *"; + case eContextTypeLLDBType: return "Type *"; + case eContextTypeVariable: return "Variable *"; }; return "???"; } Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Wed Jul 6 20:59:51 2011 @@ -973,7 +973,7 @@ unsigned long long ull_val = strtoull(value_str, &end, 0); if (end && *end != '\0') return false; - m_value = ull_val; + m_value.GetScalar() = ull_val; // Limit the bytes in our m_data appropriately. m_value.GetScalar().GetData (m_data, byte_size); } @@ -989,7 +989,7 @@ long long sll_val = strtoll(value_str, &end, 0); if (end && *end != '\0') return false; - m_value = sll_val; + m_value.GetScalar() = sll_val; // Limit the bytes in our m_data appropriately. m_value.GetScalar().GetData (m_data, byte_size); } @@ -1612,7 +1612,7 @@ data.SetByteOrder (m_data.GetByteOrder()); data.SetAddressByteSize(m_data.GetAddressByteSize()); - m_error = m_value.GetValueAsData (&exe_ctx, ast, data, 0); + m_error = m_value.GetValueAsData (&exe_ctx, ast, data, 0, GetModule()); valobj_sp = ValueObjectConstResult::Create (exe_scope, ast, Modified: lldb/trunk/source/Core/ValueObjectChild.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectChild.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObjectChild.cpp (original) +++ lldb/trunk/source/Core/ValueObjectChild.cpp Wed Jul 6 20:59:51 2011 @@ -169,7 +169,7 @@ if (m_error.Success()) { ExecutionContext exe_ctx (GetExecutionContextScope()); - m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST (), m_data, 0); + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST (), m_data, 0, GetModule()); } } else Modified: lldb/trunk/source/Core/ValueObjectDynamicValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectDynamicValue.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObjectDynamicValue.cpp (original) +++ lldb/trunk/source/Core/ValueObjectDynamicValue.cpp Wed Jul 6 20:59:51 2011 @@ -177,7 +177,7 @@ if (m_type_sp) SetValueDidChange(true); m_value = m_parent->GetValue(); - m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule()); return m_error.Success(); } @@ -225,7 +225,7 @@ { // The variable value is in the Scalar value inside the m_value. // We can point our m_data right to it. - m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule()); if (m_error.Success()) { if (ClangASTContext::IsAggregateType (GetClangType())) Modified: lldb/trunk/source/Core/ValueObjectMemory.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectMemory.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObjectMemory.cpp (original) +++ lldb/trunk/source/Core/ValueObjectMemory.cpp Wed Jul 6 20:59:51 2011 @@ -205,7 +205,7 @@ case Value::eValueTypeScalar: // The variable value is in the Scalar value inside the m_value. // We can point our m_data right to it. - m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule()); break; case Value::eValueTypeFileAddress: @@ -247,7 +247,7 @@ else value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType()); - m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0); + m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0, GetModule()); } break; } @@ -267,3 +267,11 @@ return true; } + +Module * +ValueObjectMemory::GetModule() +{ + return m_address.GetModule(); +} + + Modified: lldb/trunk/source/Core/ValueObjectVariable.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectVariable.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObjectVariable.cpp (original) +++ lldb/trunk/source/Core/ValueObjectVariable.cpp Wed Jul 6 20:59:51 2011 @@ -20,6 +20,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolContextScope.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/Variable.h" @@ -154,7 +155,7 @@ case Value::eValueTypeScalar: // The variable value is in the Scalar value inside the m_value. // We can point our m_data right to it. - m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0); + m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule()); break; case Value::eValueTypeFileAddress: @@ -206,7 +207,7 @@ // so it can extract read its value into m_data appropriately Value value(m_value); value.SetContext(Value::eContextTypeVariable, variable); - m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0); + m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0, GetModule()); } break; } @@ -233,3 +234,20 @@ return m_variable_sp->IsInScope (frame); } +Module * +ValueObjectVariable::GetModule() +{ + if (m_variable_sp) + { + SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope(); + if (sc_scope) + { + SymbolContext sc; + sc_scope->CalculateSymbolContext (&sc); + return sc.module_sp.get(); + } + } + return NULL; +} + + Modified: lldb/trunk/source/Expression/DWARFExpression.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/DWARFExpression.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Expression/DWARFExpression.cpp (original) +++ lldb/trunk/source/Expression/DWARFExpression.cpp Wed Jul 6 20:59:51 2011 @@ -896,7 +896,7 @@ // address and whose size is the size of an address on the target machine. //---------------------------------------------------------------------- case DW_OP_addr: - stack.push_back(opcodes.GetAddress(&offset)); + stack.push_back(Scalar(opcodes.GetAddress(&offset))); stack.back().SetValueType (Value::eValueTypeFileAddress); break; @@ -1157,16 +1157,16 @@ // DW_OP_constu unsigned LEB128 integer constant // DW_OP_consts signed LEB128 integer constant //---------------------------------------------------------------------- - case DW_OP_const1u : stack.push_back(( uint8_t)opcodes.GetU8(&offset)); break; - case DW_OP_const1s : stack.push_back(( int8_t)opcodes.GetU8(&offset)); break; - case DW_OP_const2u : stack.push_back((uint16_t)opcodes.GetU16(&offset)); break; - case DW_OP_const2s : stack.push_back(( int16_t)opcodes.GetU16(&offset)); break; - case DW_OP_const4u : stack.push_back((uint32_t)opcodes.GetU32(&offset)); break; - case DW_OP_const4s : stack.push_back(( int32_t)opcodes.GetU32(&offset)); break; - case DW_OP_const8u : stack.push_back((uint64_t)opcodes.GetU64(&offset)); break; - case DW_OP_const8s : stack.push_back(( int64_t)opcodes.GetU64(&offset)); break; - case DW_OP_constu : stack.push_back(opcodes.GetULEB128(&offset)); break; - case DW_OP_consts : stack.push_back(opcodes.GetSLEB128(&offset)); break; + case DW_OP_const1u : stack.push_back(Scalar(( uint8_t)opcodes.GetU8 (&offset))); break; + case DW_OP_const1s : stack.push_back(Scalar(( int8_t)opcodes.GetU8 (&offset))); break; + case DW_OP_const2u : stack.push_back(Scalar((uint16_t)opcodes.GetU16 (&offset))); break; + case DW_OP_const2s : stack.push_back(Scalar(( int16_t)opcodes.GetU16 (&offset))); break; + case DW_OP_const4u : stack.push_back(Scalar((uint32_t)opcodes.GetU32 (&offset))); break; + case DW_OP_const4s : stack.push_back(Scalar(( int32_t)opcodes.GetU32 (&offset))); break; + case DW_OP_const8u : stack.push_back(Scalar((uint64_t)opcodes.GetU64 (&offset))); break; + case DW_OP_const8s : stack.push_back(Scalar(( int64_t)opcodes.GetU64 (&offset))); break; + case DW_OP_constu : stack.push_back(Scalar(opcodes.GetULEB128 (&offset))); break; + case DW_OP_consts : stack.push_back(Scalar(opcodes.GetSLEB128 (&offset))); break; //---------------------------------------------------------------------- // OPCODE: DW_OP_dup @@ -1877,7 +1877,7 @@ case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: - stack.push_back(op - DW_OP_lit0); + stack.push_back(Scalar(op - DW_OP_lit0)); break; //---------------------------------------------------------------------- @@ -2567,6 +2567,10 @@ error_ptr->SetErrorStringWithFormat ("DW_OP_APPLE_expr_local(%u) with invalid index %u.\n", idx, idx); return false; } + // The proxy code has been removed. If it is ever re-added, please + // use shared pointers or return by value to avoid possible memory + // leak (there is no leak here, but in general, no returning pointers + // that must be manually freed please. Value *proxy = expr_local_variable->CreateProxy(); stack.push_back(*proxy); delete proxy; @@ -2598,6 +2602,10 @@ error_ptr->SetErrorStringWithFormat ("DW_OP_APPLE_extern(%u) with invalid index %u.\n", idx, idx); return false; } + // The proxy code has been removed. If it is ever re-added, please + // use shared pointers or return by value to avoid possible memory + // leak (there is no leak here, but in general, no returning pointers + // that must be manually freed please. Value *proxy = extern_var->CreateProxy(); stack.push_back(*proxy); delete proxy; Modified: lldb/trunk/source/Interpreter/NamedOptionValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/NamedOptionValue.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/NamedOptionValue.cpp (original) +++ lldb/trunk/source/Interpreter/NamedOptionValue.cpp Wed Jul 6 20:59:51 2011 @@ -315,6 +315,27 @@ return Error(); } +//------------------------------------------------------------------------- +// OptionValueFileSpecList +//------------------------------------------------------------------------- +void +OptionValueFileSpecList::DumpValue (Stream &strm) +{ + m_current_value.Dump(&strm, "\n"); +} + +Error +OptionValueFileSpecList::SetValueFromCString (const char *value_cstr) +{ + if (value_cstr && value_cstr[0]) + { + FileSpec file (value_cstr, false); + m_current_value.Append(file); + } + m_value_was_set = true; + return Error(); +} + //------------------------------------------------------------------------- // OptionValueUUID Modified: lldb/trunk/source/Interpreter/OptionGroupFile.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupFile.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/OptionGroupFile.cpp (original) +++ lldb/trunk/source/Interpreter/OptionGroupFile.cpp Wed Jul 6 20:59:51 2011 @@ -55,3 +55,43 @@ { m_file.Clear(); } + + +OptionGroupFileList::OptionGroupFileList (uint32_t usage_mask, + bool required, + const char *long_option, + char short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text) : + m_file_list () +{ + m_option_definition.usage_mask = usage_mask; + m_option_definition.required = required; + m_option_definition.long_option = long_option; + m_option_definition.short_option = short_option; + m_option_definition.option_has_arg = required_argument; + m_option_definition.enum_values = NULL; + m_option_definition.completion_type = completion_type; + m_option_definition.argument_type = argument_type; + m_option_definition.usage_text = usage_text; +} + +OptionGroupFileList::~OptionGroupFileList () +{ +} + +Error +OptionGroupFileList::SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) +{ + Error error (m_file_list.SetValueFromCString (option_arg)); + return error; +} + +void +OptionGroupFileList::OptionParsingStarting (CommandInterpreter &interpreter) +{ + m_file_list.Clear(); +} Modified: lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp (original) +++ lldb/trunk/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp Wed Jul 6 20:59:51 2011 @@ -407,7 +407,11 @@ // Now get a pointer value from the zeroth argument. Error error; DataExtractor data; - error = argument_values.GetValueAtIndex(0)->GetValueAsData(&(context->exe_ctx), clang_ast_context->getASTContext(), data, 0); + error = argument_values.GetValueAtIndex(0)->GetValueAsData (&(context->exe_ctx), + clang_ast_context->getASTContext(), + data, + 0, + NULL); uint32_t offset_ptr = 0; lldb::addr_t region_addr = data.GetPointer(&offset_ptr); Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Wed Jul 6 20:59:51 2011 @@ -190,6 +190,8 @@ uint8_t buffer[8192]; Error error; + LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE)); + // Check for a packet from our cache first without trying any reading... if (CheckForPacket (NULL, 0, packet)) return packet.GetStringRef().size(); @@ -199,6 +201,15 @@ { lldb::ConnectionStatus status; size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); + + if (log) + log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %zu", + __PRETTY_FUNCTION__, + timeout_usec, + Communication::ConnectionStatusAsCString (status), + error.AsCString(), + bytes_read); + if (bytes_read > 0) { if (CheckForPacket (buffer, bytes_read, packet)) Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original) +++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Wed Jul 6 20:59:51 2011 @@ -237,11 +237,16 @@ { Mutex::Locker locker; LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); - + size_t response_len = 0; if (GetSequenceMutex (locker)) { if (SendPacketNoLock (payload, payload_length)) - return WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()); + response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()); + else + { + if (log) + log->Printf("error: failed to send '%*s'", payload_length, payload); + } } else { @@ -266,12 +271,15 @@ if (log) log->Printf ("async: sent interrupt"); + if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out)) { if (log) log->Printf ("async: got response"); - response = m_async_response; - return response.GetStringRef().size(); + + // Swap the response buffer to avoid malloc and string copy + response.GetStringRef().swap (m_async_response.GetStringRef()); + response_len = response.GetStringRef().size(); } else { @@ -289,7 +297,9 @@ else { // We had a racy condition where we went to send the interrupt - // yet we were able to get the loc + // yet we were able to get the lock + if (log) + log->Printf ("async: got lock but failed to send interrupt"); } } else @@ -301,10 +311,15 @@ else { if (log) - log->Printf ("mutex taken and send_async == false, aborting packet"); + log->Printf("error: packet mutex taken and send_async == false, not sending packet '%*s'", payload_length, payload); } } - return 0; + if (response_len == 0) + { + if (log) + log->Printf("error: failed to get response for '%*s'", payload_length, payload); + } + return response_len; } //template Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Jul 6 20:59:51 2011 @@ -3381,8 +3381,6 @@ clang_type = m_forward_decl_die_to_clang_type.lookup (die); if (clang_type == NULL) { - if (die->GetOffset() == 0x1c436) - printf("REMOVE THIS!!!\n"); enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL, DW_ATE_signed, byte_size * 8); Modified: lldb/trunk/source/Symbol/CompileUnit.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/CompileUnit.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Symbol/CompileUnit.cpp (original) +++ lldb/trunk/source/Symbol/CompileUnit.cpp Wed Jul 6 20:59:51 2011 @@ -285,7 +285,7 @@ // "file_spec" has an empty directory, then only compare the basenames // when finding file indexes std::vector file_indexes; - bool file_spec_matches_cu_file_spec = FileSpec::Compare(file_spec, this, !file_spec.GetDirectory().IsEmpty()) == 0; + bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, this, !file_spec.GetDirectory().IsEmpty()); // If we are not looking for inlined functions and our file spec doesn't // match then we are done... Modified: lldb/trunk/source/Target/ExecutionContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ExecutionContext.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Target/ExecutionContext.cpp (original) +++ lldb/trunk/source/Target/ExecutionContext.cpp Wed Jul 6 20:59:51 2011 @@ -99,3 +99,13 @@ return process; return target; } + +Process * +ExecutionContext::GetProcess () const +{ + if (process) + return process; + if (target) + return target->GetProcessSP().get(); + return NULL; +} Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Wed Jul 6 20:59:51 2011 @@ -444,7 +444,6 @@ m_arch)); if (image_module_sp.get()) { - //image_module_sp->Dump(&s);// REMOVE THIS, DEBUG ONLY ObjectFile *objfile = image_module_sp->GetObjectFile(); if (objfile) objfile->GetDependentModules(dependent_files); Modified: lldb/trunk/tools/lldb-platform/lldb-platform.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-platform/lldb-platform.cpp?rev=134579&r1=134578&r2=134579&view=diff ============================================================================== --- lldb/trunk/tools/lldb-platform/lldb-platform.cpp (original) +++ lldb/trunk/tools/lldb-platform/lldb-platform.cpp Wed Jul 6 20:59:51 2011 @@ -211,6 +211,11 @@ if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done)) break; } + + if (error.Fail()) + { + fprintf(stderr, "error: %s\n", error.AsCString()); + } } else { From jingham at apple.com Wed Jul 6 21:22:51 2011 From: jingham at apple.com (Jim Ingham) Date: Thu, 07 Jul 2011 02:22:51 -0000 Subject: [Lldb-commits] [lldb] r134584 - in /lldb/trunk/include/lldb/Core: Module.h ModuleList.h Message-ID: <20110707022251.379CB2A6C12C@llvm.org> Author: jingham Date: Wed Jul 6 21:22:51 2011 New Revision: 134584 URL: http://llvm.org/viewvc/llvm-project?rev=134584&view=rev Log: Typo in header doc. Modified: lldb/trunk/include/lldb/Core/Module.h lldb/trunk/include/lldb/Core/ModuleList.h Modified: lldb/trunk/include/lldb/Core/Module.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=134584&r1=134583&r2=134584&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Module.h (original) +++ lldb/trunk/include/lldb/Core/Module.h Wed Jul 6 21:22:51 2011 @@ -187,7 +187,7 @@ /// Find functions by name. /// /// @param[in] name - /// The name of the function we are looking for. + /// The name of the compile unit we are looking for. /// /// @param[in] name_type_mask /// A bit mask of bits that indicate what kind of names should Modified: lldb/trunk/include/lldb/Core/ModuleList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ModuleList.h?rev=134584&r1=134583&r2=134584&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ModuleList.h (original) +++ lldb/trunk/include/lldb/Core/ModuleList.h Wed Jul 6 21:22:51 2011 @@ -146,7 +146,7 @@ /// and returns the results in \a sc_list. /// /// @param[in] path - /// The name of the function we are looking for. + /// The name of the compile unit we are looking for. /// /// @param[in] append /// If \b true, then append any compile units that were found From gclayton at apple.com Wed Jul 6 23:38:25 2011 From: gclayton at apple.com (Greg Clayton) Date: Thu, 07 Jul 2011 04:38:25 -0000 Subject: [Lldb-commits] [lldb] r134594 - in /lldb/trunk: include/lldb/Interpreter/OptionGroupVariable.h lldb.xcodeproj/project.pbxproj source/Commands/CommandObjectFrame.cpp source/Commands/CommandObjectTarget.cpp source/Interpreter/OptionGroupVariable.cpp test/lang/cpp/class_static/TestStaticVariables.py Message-ID: <20110707043825.53B3D2A6C12D@llvm.org> Author: gclayton Date: Wed Jul 6 23:38:25 2011 New Revision: 134594 URL: http://llvm.org/viewvc/llvm-project?rev=134594&view=rev Log: Centralize the variable display prefs into a new option group class: OptionGroupVariable. It gets initialized with a boolean that indicates if the frame specific options are included so that this can be used in both the "frame variable" and "target variable" commands. Removed the global functionality from the "frame variable" command. Users should switch to using the "target variable" command. Added: lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h lldb/trunk/source/Interpreter/OptionGroupVariable.cpp Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Commands/CommandObjectFrame.cpp lldb/trunk/source/Commands/CommandObjectTarget.cpp lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py Added: lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h?rev=134594&view=auto ============================================================================== --- lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h (added) +++ lldb/trunk/include/lldb/Interpreter/OptionGroupVariable.h Wed Jul 6 23:38:25 2011 @@ -0,0 +1,63 @@ +//===-- OptionGroupVariable.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_OptionGroupVariable_h_ +#define liblldb_OptionGroupVariable_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// OptionGroupVariable +//------------------------------------------------------------------------- + + class OptionGroupVariable : public OptionGroup + { + public: + + OptionGroupVariable (bool show_frame_options); + + virtual + ~OptionGroupVariable (); + + virtual uint32_t + GetNumDefinitions (); + + virtual const OptionDefinition* + GetDefinitions (); + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + bool include_frame_options:1, + show_args:1, // Frame option only (include_frame_options == true) + show_locals:1, // Frame option only (include_frame_options == true) + show_globals:1, // Frame option only (include_frame_options == true) + use_regex:1, + show_scope:1, + show_decl:1; + lldb::Format format; + + private: + DISALLOW_COPY_AND_ASSIGN(OptionGroupVariable); + }; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupVariable_h_ Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134594&r1=134593&r2=134594&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Wed Jul 6 23:38:25 2011 @@ -380,6 +380,7 @@ 26DE20631161904200A093E2 /* SBLineEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE20621161904200A093E2 /* SBLineEntry.cpp */; }; 26DE20651161904E00A093E2 /* SBSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE20641161904E00A093E2 /* SBSymbol.cpp */; }; 26ECA04313665FED008D1F18 /* ARM_DWARF_Registers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */; }; + 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */; }; 26F5C27710F3D9E4009D5894 /* Driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27310F3D9E4009D5894 /* Driver.cpp */; }; 26F5C27810F3D9E4009D5894 /* IOChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27510F3D9E4009D5894 /* IOChannel.cpp */; }; 26F5C32510F3DF23009D5894 /* libpython.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32410F3DF23009D5894 /* libpython.dylib */; }; @@ -1048,6 +1049,8 @@ 26E6902E129C6BD500DDECD9 /* ClangExternalASTSourceCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExternalASTSourceCallbacks.h; path = include/lldb/Symbol/ClangExternalASTSourceCallbacks.h; sourceTree = ""; }; 26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExternalASTSourceCallbacks.cpp; path = source/Symbol/ClangExternalASTSourceCallbacks.cpp; sourceTree = ""; }; 26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ARM_DWARF_Registers.cpp; path = source/Utility/ARM_DWARF_Registers.cpp; sourceTree = ""; }; + 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupVariable.cpp; path = source/Interpreter/OptionGroupVariable.cpp; sourceTree = ""; }; + 26ED3D6F13C5638A0017D45E /* OptionGroupVariable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupVariable.h; path = include/lldb/Interpreter/OptionGroupVariable.h; sourceTree = ""; }; 26F5C26A10F3D9A4009D5894 /* lldb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lldb; sourceTree = BUILT_PRODUCTS_DIR; }; 26F5C27210F3D9E4009D5894 /* lldb-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-Info.plist"; path = "tools/driver/lldb-Info.plist"; sourceTree = ""; }; 26F5C27310F3D9E4009D5894 /* Driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Driver.cpp; path = tools/driver/Driver.cpp; sourceTree = ""; }; @@ -2263,6 +2266,8 @@ 260E07C5136FA69E00CF21D3 /* OptionGroupUUID.cpp */, 267C0128136880C7006E963E /* OptionGroupValueObjectDisplay.h */, 267C012A136880DF006E963E /* OptionGroupValueObjectDisplay.cpp */, + 26ED3D6F13C5638A0017D45E /* OptionGroupVariable.h */, + 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */, 26BC7DE510F1B7F900F91463 /* ScriptInterpreter.h */, 9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */, 9A2771FB1135A35C00E6ADB6 /* ScriptInterpreterNone.h */, @@ -3245,6 +3250,7 @@ 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */, 49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */, 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */, + 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=134594&r1=134593&r2=134594&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Wed Jul 6 23:38:25 2011 @@ -26,6 +26,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/Interpreter/OptionGroupVariable.h" #include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" @@ -378,7 +379,7 @@ NULL, eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), m_option_group (interpreter), - m_frame_var_options(), + m_option_variable(true), // Include the frame specific options by passing "true" m_varobj_options() { CommandArgumentEntry arg; @@ -394,7 +395,7 @@ // Push the data for the first argument into the m_arguments vector. m_arguments.push_back (arg); - m_option_group.Append (&m_frame_var_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Finalize(); } @@ -438,73 +439,8 @@ const char *name_cstr = NULL; size_t idx; - if (!m_frame_var_options.globals.empty()) - { - uint32_t fail_count = 0; - if (exe_ctx.target) - { - const size_t num_globals = m_frame_var_options.globals.size(); - for (idx = 0; idx < num_globals; ++idx) - { - VariableList global_var_list; - const uint32_t num_matching_globals - = exe_ctx.target->GetImages().FindGlobalVariables (m_frame_var_options.globals[idx], - true, - UINT32_MAX, - global_var_list); - if (num_matching_globals == 0) - { - ++fail_count; - result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", - m_frame_var_options.globals[idx].AsCString()); - } - else - { - for (uint32_t global_idx=0; global_idxGetValueObjectForFrameVariable (var_sp, - m_varobj_options.use_dynamic); - if (!valobj_sp) - valobj_sp = exe_ctx.frame->TrackGlobalVariable (var_sp, - m_varobj_options.use_dynamic); - - if (valobj_sp) - { - if (m_frame_var_options.format != eFormatDefault) - valobj_sp->SetFormat (m_frame_var_options.format); - - if (m_frame_var_options.show_decl && var_sp->GetDeclaration ().GetFile()) - { - var_sp->GetDeclaration ().DumpStopContext (&s, false); - s.PutCString (": "); - } - - ValueObject::DumpValueObject (result.GetOutputStream(), - valobj_sp.get(), - name_cstr, - m_varobj_options.ptr_depth, - 0, - m_varobj_options.max_depth, - m_varobj_options.show_types, - m_varobj_options.show_location, - m_varobj_options.use_objc, - m_varobj_options.use_dynamic, - false, - m_varobj_options.flat_output); - } - } - } - } - } - } - if (fail_count) - result.SetStatus (eReturnStatusFailed); - } - else if (variable_list) + if (variable_list) { if (command.GetArgumentCount() > 0) { @@ -516,7 +452,7 @@ { uint32_t ptr_depth = m_varobj_options.ptr_depth; - if (m_frame_var_options.use_regex) + if (m_option_variable.use_regex) { const uint32_t regex_start_index = regex_var_list.GetSize(); RegularExpression regex (name_cstr); @@ -538,10 +474,10 @@ valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic); if (valobj_sp) { - if (m_frame_var_options.format != eFormatDefault) - valobj_sp->SetFormat (m_frame_var_options.format); + if (m_option_variable.format != eFormatDefault) + valobj_sp->SetFormat (m_option_variable.format); - if (m_frame_var_options.show_decl && var_sp->GetDeclaration ().GetFile()) + if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); @@ -589,9 +525,9 @@ error); if (valobj_sp) { - if (m_frame_var_options.format != eFormatDefault) - valobj_sp->SetFormat (m_frame_var_options.format); - if (m_frame_var_options.show_decl && var_sp && var_sp->GetDeclaration ().GetFile()) + if (m_option_variable.format != eFormatDefault) + valobj_sp->SetFormat (m_option_variable.format); + if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); @@ -635,26 +571,26 @@ switch (var_sp->GetScope()) { case eValueTypeVariableGlobal: - dump_variable = m_frame_var_options.show_globals; - if (dump_variable && m_frame_var_options.show_scope) + dump_variable = m_option_variable.show_globals; + if (dump_variable && m_option_variable.show_scope) s.PutCString("GLOBAL: "); break; case eValueTypeVariableStatic: - dump_variable = m_frame_var_options.show_globals; - if (dump_variable && m_frame_var_options.show_scope) + dump_variable = m_option_variable.show_globals; + if (dump_variable && m_option_variable.show_scope) s.PutCString("STATIC: "); break; case eValueTypeVariableArgument: - dump_variable = m_frame_var_options.show_args; - if (dump_variable && m_frame_var_options.show_scope) + dump_variable = m_option_variable.show_args; + if (dump_variable && m_option_variable.show_scope) s.PutCString(" ARG: "); break; case eValueTypeVariableLocal: - dump_variable = m_frame_var_options.show_locals; - if (dump_variable && m_frame_var_options.show_scope) + dump_variable = m_option_variable.show_locals; + if (dump_variable && m_option_variable.show_scope) s.PutCString(" LOCAL: "); break; @@ -672,14 +608,14 @@ m_varobj_options.use_dynamic); if (valobj_sp) { - if (m_frame_var_options.format != eFormatDefault) - valobj_sp->SetFormat (m_frame_var_options.format); + if (m_option_variable.format != eFormatDefault) + valobj_sp->SetFormat (m_option_variable.format); // When dumping all variables, don't print any variables // that are not in scope to avoid extra unneeded output if (valobj_sp->IsInScope ()) { - if (m_frame_var_options.show_decl && var_sp->GetDeclaration ().GetFile()) + if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); @@ -710,30 +646,10 @@ protected: OptionGroupOptions m_option_group; - OptionGroupFrameVariable m_frame_var_options; + OptionGroupVariable m_option_variable; OptionGroupValueObjectDisplay m_varobj_options; }; -OptionDefinition -CommandObjectFrameVariable::OptionGroupFrameVariable::g_option_table[] = -{ -{ LLDB_OPT_SET_1, false, "no-args", 'a', no_argument, NULL, 0, eArgTypeNone, "Omit function arguments."}, -{ LLDB_OPT_SET_1, false, "show-declaration",'c', no_argument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."}, -{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format that the variable output should use."}, -{ LLDB_OPT_SET_1, false, "show-globals", 'g', no_argument, NULL, 0, eArgTypeNone, "Show the current frame source file global and static variables."}, -{ LLDB_OPT_SET_1, false, "find-global", 'G', required_argument, NULL, 0, eArgTypeVarName, "Find a global variable by name (which might not be in the current stack frame source file)."}, -{ LLDB_OPT_SET_1, false, "no-locals", 'l', no_argument, NULL, 0, eArgTypeNone, "Omit local variables."}, -{ LLDB_OPT_SET_1, false, "regex", 'r', no_argument, NULL, 0, eArgTypeRegularExpression, "The argument for name lookups are regular expressions."}, -{ LLDB_OPT_SET_1, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."}, -{ 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL } -}; - -uint32_t -CommandObjectFrameVariable::OptionGroupFrameVariable::GetNumDefinitions () -{ - return sizeof(CommandObjectFrameVariable::OptionGroupFrameVariable::g_option_table)/sizeof(OptionDefinition); -} - #pragma mark CommandObjectMultiwordFrame Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=134594&r1=134593&r2=134594&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Wed Jul 6 23:38:25 2011 @@ -27,7 +27,7 @@ #include "lldb/Interpreter/Options.h" #include "lldb/Interpreter/OptionGroupArchitecture.h" #include "lldb/Interpreter/OptionGroupFile.h" -#include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionGroupVariable.h" #include "lldb/Interpreter/OptionGroupPlatform.h" #include "lldb/Interpreter/OptionGroupUInt64.h" #include "lldb/Interpreter/OptionGroupUUID.h" @@ -417,13 +417,13 @@ NULL, 0), m_option_group (interpreter), - m_format_options (eFormatDefault, 0, false), + m_option_variable (false), // Don't include frame options m_option_compile_units (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypePath, "A basename or fullpath to a file that contains global variables. This option can be specified multiple times."), m_option_shared_libraries (LLDB_OPT_SET_1, false, "shlib",'s', 0, eArgTypePath, "A basename or fullpath to a shared library to use in the search for global variables. This option can be specified multiple times."), m_varobj_options() { m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); - m_option_group.Append (&m_format_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); + m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_option_compile_units, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Append (&m_option_shared_libraries, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); m_option_group.Finalize(); @@ -447,19 +447,39 @@ for (size_t idx = 0; idx < argc; ++idx) { VariableList global_var_list; - const char *global_var_name = args.GetArgumentAtIndex(idx); - const uint32_t matches = exe_ctx.target->GetImages().FindGlobalVariables (global_var_name, - true, - UINT32_MAX, - global_var_list); + const char *arg = args.GetArgumentAtIndex(idx); + uint32_t matches = 0; + if (m_option_variable.use_regex) + { + RegularExpression regex(arg); + if (!regex.IsValid ()) + { + result.GetErrorStream().Printf ("error: invalid regular expression: '%s'\n", arg); + result.SetStatus (eReturnStatusFailed); + return false; + } + matches = exe_ctx.target->GetImages().FindGlobalVariables (regex, + true, + UINT32_MAX, + global_var_list); + } + else + { + matches = exe_ctx.target->GetImages().FindGlobalVariables (arg, + true, + UINT32_MAX, + global_var_list); + } if (matches == 0) { - result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", - global_var_name); + result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", arg); + result.SetStatus (eReturnStatusFailed); + return false; } else { + Stream &s = result.GetOutputStream(); for (uint32_t global_idx=0; global_idxSetFormat (m_option_variable.format); + + switch (var_sp->GetScope()) + { + case eValueTypeVariableGlobal: + if (m_option_variable.show_scope) + s.PutCString("GLOBAL: "); + break; + + case eValueTypeVariableStatic: + if (m_option_variable.show_scope) + s.PutCString("STATIC: "); + break; + + case eValueTypeVariableArgument: + if (m_option_variable.show_scope) + s.PutCString(" ARG: "); + break; + + case eValueTypeVariableLocal: + if (m_option_variable.show_scope) + s.PutCString(" LOCAL: "); + break; + + default: + break; + } + + if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) + { + var_sp->GetDeclaration ().DumpStopContext (&s, false); + s.PutCString (": "); + } + + const Format format = m_option_variable.format; if (format != eFormatDefault) valobj_sp->SetFormat (format); -// if (m_format_options.show_decl && var_sp->GetDeclaration ().GetFile()) -// { -// var_sp->GetDeclaration ().DumpStopContext (&s, false); -// s.PutCString (": "); -// } - - ValueObject::DumpValueObject (result.GetOutputStream(), + ValueObject::DumpValueObject (s, valobj_sp.get(), - global_var_name, + var_sp->GetName().GetCString(), m_varobj_options.ptr_depth, 0, m_varobj_options.max_depth, @@ -520,7 +569,7 @@ protected: OptionGroupOptions m_option_group; - OptionGroupFormat m_format_options; + OptionGroupVariable m_option_variable; OptionGroupFileList m_option_compile_units; OptionGroupFileList m_option_shared_libraries; OptionGroupValueObjectDisplay m_varobj_options; Added: lldb/trunk/source/Interpreter/OptionGroupVariable.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/OptionGroupVariable.cpp?rev=134594&view=auto ============================================================================== --- lldb/trunk/source/Interpreter/OptionGroupVariable.cpp (added) +++ lldb/trunk/source/Interpreter/OptionGroupVariable.cpp Wed Jul 6 23:38:25 2011 @@ -0,0 +1,109 @@ +//===-- OptionGroupVariable.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/Interpreter/OptionGroupVariable.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Target.h" +#include "lldb/Interpreter/CommandInterpreter.h" + +using namespace lldb; +using namespace lldb_private; + +static OptionDefinition +g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "no-args", 'a', no_argument, NULL, 0, eArgTypeNone, "Omit function arguments."}, + { LLDB_OPT_SET_1, false, "no-locals", 'l', no_argument, NULL, 0, eArgTypeNone, "Omit local variables."}, + { LLDB_OPT_SET_1, false, "show-globals", 'g', no_argument, NULL, 0, eArgTypeNone, "Show the current frame source file global and static variables."}, + { LLDB_OPT_SET_1, false, "show-declaration",'c', no_argument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."}, + { LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format that the variable output should use."}, + { LLDB_OPT_SET_1, false, "regex", 'r', no_argument, NULL, 0, eArgTypeRegularExpression, "The argument for name lookups are regular expressions."}, + { LLDB_OPT_SET_1, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."} +}; + + +OptionGroupVariable::OptionGroupVariable (bool show_frame_options) : + OptionGroup(), + include_frame_options (show_frame_options) +{ +} + +OptionGroupVariable::~OptionGroupVariable () +{ +} + +Error +OptionGroupVariable::SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_arg) +{ + Error error; + if (!include_frame_options) + option_idx += 3; + char short_option = (char) g_option_table[option_idx].short_option; + switch (short_option) + { + case 'r': use_regex = true; break; + case 'a': show_args = false; break; + case 'l': show_locals = false; break; + case 'g': show_globals = true; break; + case 'c': show_decl = true; break; + case 'f': error = Args::StringToFormat(option_arg, format, NULL); break; + case 's': + show_scope = true; + break; + + default: + error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); + break; + } + + return error; +} + +void +OptionGroupVariable::OptionParsingStarting (CommandInterpreter &interpreter) +{ + show_args = true; // Frame option only + show_locals = true; // Frame option only + show_globals = false; // Frame option only + show_decl = false; + format = lldb::eFormatDefault; + use_regex = false; + show_scope = false; +} + + +const OptionDefinition* +OptionGroupVariable::GetDefinitions () +{ + // Show the "--no-args", "--no-locals" and "--show-globals" + // options if we are showing frame specific options + if (include_frame_options) + return g_option_table; + + // Skip the "--no-args", "--no-locals" and "--show-globals" + // options if we are not showing frame specific options (globals only) + return &g_option_table[3]; +} + +uint32_t +OptionGroupVariable::GetNumDefinitions () +{ + if (include_frame_options) + return 7; + else + return 4; +} + + Modified: lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py?rev=134594&r1=134593&r2=134594&view=diff ============================================================================== --- lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py (original) +++ lldb/trunk/test/lang/cpp/class_static/TestStaticVariables.py Wed Jul 6 23:38:25 2011 @@ -60,9 +60,11 @@ # On Mac OS X, gcc 4.2 emits the wrong debug info for A::g_points. slist = ['(PointType [2]) g_points', 'A::g_points'] +# global variables are no longer displayed with the "frame variable" command. +# add tests for the "target variable" command soon # 'frame variable -G' finds and displays global variable(s) by name. - self.expect('frame variable -G g_points', VARIABLES_DISPLAYED_CORRECTLY, - substrs = slist) + # self.expect('frame variable -G g_points', VARIABLES_DISPLAYED_CORRECTLY, + # substrs = slist) # A::g_points is an array of two elements. if sys.platform.startswith("darwin") and self.getCompiler() in ['clang', 'llvm-gcc']: From gclayton at apple.com Wed Jul 6 23:49:07 2011 From: gclayton at apple.com (Greg Clayton) Date: Thu, 07 Jul 2011 04:49:07 -0000 Subject: [Lldb-commits] [lldb] r134598 - in /lldb/trunk: include/lldb/Core/RegularExpression.h source/Commands/CommandObjectTarget.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Message-ID: <20110707044907.A27782A6C12D@llvm.org> Author: gclayton Date: Wed Jul 6 23:49:07 2011 New Revision: 134598 URL: http://llvm.org/viewvc/llvm-project?rev=134598&view=rev Log: Stop the lldb_private::RegularExpression class from implicitly constructing itself and causing unexpected things to happen in LLDB. Modified: lldb/trunk/include/lldb/Core/RegularExpression.h lldb/trunk/source/Commands/CommandObjectTarget.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Modified: lldb/trunk/include/lldb/Core/RegularExpression.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/RegularExpression.h?rev=134598&r1=134597&r2=134598&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/RegularExpression.h (original) +++ lldb/trunk/include/lldb/Core/RegularExpression.h Wed Jul 6 23:49:07 2011 @@ -51,6 +51,7 @@ /// @param[in] flags /// Flags that are passed the the \c regcomp() function. //------------------------------------------------------------------ + explicit RegularExpression (const char* re, int flags = REG_EXTENDED); //------------------------------------------------------------------ Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=134598&r1=134597&r2=134598&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Wed Jul 6 23:49:07 2011 @@ -465,7 +465,7 @@ } else { - matches = exe_ctx.target->GetImages().FindGlobalVariables (arg, + matches = exe_ctx.target->GetImages().FindGlobalVariables (ConstString(arg), true, UINT32_MAX, global_var_list); Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=134598&r1=134597&r2=134598&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Jul 6 23:49:07 2011 @@ -4428,7 +4428,7 @@ std::vector die_info_array; - size_t num_matches = m_type_index.Find (name, die_info_array); + size_t num_matches = m_type_index.Find (ConstString(name), die_info_array); if (num_matches) { From granata.enrico at gmail.com Thu Jul 7 10:49:54 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Thu, 07 Jul 2011 15:49:54 -0000 Subject: [Lldb-commits] [lldb] r134613 - in /lldb/trunk: include/lldb/Interpreter/CommandObject.h source/Interpreter/CommandObject.cpp Message-ID: <20110707154954.8DDBE2A6C12C@llvm.org> Author: enrico Date: Thu Jul 7 10:49:54 2011 New Revision: 134613 URL: http://llvm.org/viewvc/llvm-project?rev=134613&view=rev Log: Fixed a warning where initializing CommandObject::g_arguments_data[] required global constructors Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h lldb/trunk/source/Interpreter/CommandObject.cpp Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandObject.h?rev=134613&r1=134612&r2=134613&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandObject.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandObject.h Thu Jul 7 10:49:54 2011 @@ -33,24 +33,6 @@ { ArgumentHelpCallbackFunction *help_callback; bool self_formatting; - ArgumentHelpCallback(ArgumentHelpCallbackFunction *p, - bool f = false) : - help_callback(p), - self_formatting(f) - { - } - - const char* - operator () () const - { - return (*help_callback)(); - } - - operator bool() const - { - return (help_callback != NULL); - } - }; struct ArgumentTableEntry // Entries in the main argument information table Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=134613&r1=134612&r2=134613&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Jul 7 10:49:54 2011 @@ -469,9 +469,9 @@ StreamString name_str; name_str.Printf ("<%s>", entry->arg_name); - if (entry->help_function) + if (entry->help_function.help_callback) { - const char* help_text = entry->help_function(); + const char* help_text = (*entry->help_function.help_callback)(); if (!entry->help_function.self_formatting) { interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text, @@ -718,68 +718,68 @@ CommandObject::ArgumentTableEntry CommandObject::g_arguments_data[] = { - { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, NULL, "A valid address in the target program's execution space." }, - { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, NULL, "The name of an abbreviation (alias) for a debugger command." }, - { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, NULL, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" }, - { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, NULL, "The architecture name, e.g. i386 or x86_64." }, - { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, NULL, "A Boolean value: 'true' or 'false'" }, - { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, BreakpointIDHelpTextCallback, NULL }, - { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, BreakpointIDRangeHelpTextCallback, NULL }, - { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, NULL, "Number of bytes to use." }, - { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, NULL, "Then name of a class from the debug information in the program." }, - { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, NULL, "A debugger command (may be multiple words), without any options or arguments." }, - { eArgTypeCount, "count", CommandCompletions::eNoCompletion, NULL, "An unsigned integer." }, - { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, NULL, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, - { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, NULL, "The name of a file (can include path)." }, - { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, CommandObject::ArgumentHelpCallback(FormatHelpTextCallback, true), NULL }, - { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, NULL, "Index into a thread's list of frames." }, - { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, NULL, "The name of a function." }, - { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, NULL, "An index into a list." }, - { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, NULL, "Line number in a source file." }, - { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, NULL, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." }, - { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, NULL, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." }, - { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, NULL, "A C++ method name." }, - { eArgTypeName, "name", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, NULL, "The number of lines to use." }, - { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, NULL, "The number of items per line to display." }, - { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, NULL, "A command that is entered as a single line of text." }, - { eArgTypePath, "path", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypePid, "pid", CommandCompletions::eNoCompletion, NULL, "The process ID number." }, - { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, NULL, "The name of the process." }, - { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, NULL, "The name of the thread queue." }, - { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, NULL, "A register name." }, - { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, NULL, "A regular expression." }, - { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, NULL, "Arguments to be passed to the target program when it starts executing." }, - { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, NULL, "The scripting language to be used for script-based commands. Currently only Python is valid." }, - { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, NULL, "The word for which you wish to search for information about." }, - { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, NULL, "An Objective-C selector name." }, - { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, NULL, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." }, - { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, NULL, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." }, - { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, NULL, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" }, - { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, NULL, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." }, - { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, NULL, "The name of a shared library." }, - { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, NULL, "The name of a source file.." }, - { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, NULL, "Specify a sort order when dumping lists." }, - { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, CommandObject::ArgumentHelpCallback(SummaryStringHelpTextCallback, true), NULL }, - { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, NULL, "Any symbol name (function name, variable, argument, etc.)" }, - { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, NULL, "Thread ID number." }, - { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, NULL, "Index into the process' list of threads." }, - { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, NULL, "The thread's name." }, - { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, NULL, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, - { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, NULL, "The name of a variable in your program." }, - { eArgTypeValue, "value", CommandCompletions::eNoCompletion, NULL, "A value could be anything, depending on where and how it is used." }, - { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, NULL, "Help text goes here." }, - { eArgTypeNone, "none", CommandCompletions::eNoCompletion, NULL, "No help available for this." }, - { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, NULL, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." } + { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { NULL, false }, "A valid address in the target program's execution space." }, + { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of an abbreviation (alias) for a debugger command." }, + { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { NULL, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" }, + { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { NULL, false }, "The architecture name, e.g. i386 or x86_64." }, + { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { NULL, false }, "A Boolean value: 'true' or 'false'" }, + { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, NULL }, + { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, NULL }, + { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { NULL, false }, "Number of bytes to use." }, + { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { NULL, false }, "Then name of a class from the debug information in the program." }, + { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." }, + { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, + { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, + { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." }, + { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL }, + { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into a thread's list of frames." }, + { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function." }, + { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a list." }, + { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { NULL, false }, "Line number in a source file." }, + { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." }, + { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." }, + { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { NULL, false }, "A C++ method name." }, + { eArgTypeName, "name", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { NULL, false }, "The number of lines to use." }, + { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { NULL, false }, "The number of items per line to display." }, + { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { NULL, false }, "A command that is entered as a single line of text." }, + { eArgTypePath, "path", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." }, + { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." }, + { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." }, + { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { NULL, false }, "A register name." }, + { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." }, + { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { NULL, false }, "Arguments to be passed to the target program when it starts executing." }, + { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { NULL, false }, "The scripting language to be used for script-based commands. Currently only Python is valid." }, + { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { NULL, false }, "The word for which you wish to search for information about." }, + { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { NULL, false }, "An Objective-C selector name." }, + { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." }, + { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { NULL, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." }, + { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" }, + { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." }, + { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a shared library." }, + { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { NULL, false }, "The name of a source file.." }, + { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { NULL, false }, "Specify a sort order when dumping lists." }, + { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, NULL }, + { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { NULL, false }, "Any symbol name (function name, variable, argument, etc.)" }, + { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { NULL, false }, "Thread ID number." }, + { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into the process' list of threads." }, + { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { NULL, false }, "The thread's name." }, + { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { NULL, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, + { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a variable in your program." }, + { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { NULL, false }, "A value could be anything, depending on where and how it is used." }, + { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, + { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { NULL, false }, "No help available for this." }, + { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { NULL, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." } }; const CommandObject::ArgumentTableEntry* From johnny.chen at apple.com Thu Jul 7 13:50:45 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 18:50:45 -0000 Subject: [Lldb-commits] [lldb] r134623 - /lldb/trunk/include/lldb/API/SBDebugger.h Message-ID: <20110707185045.D34D42A6C12C@llvm.org> Author: johnny Date: Thu Jul 7 13:50:45 2011 New Revision: 134623 URL: http://llvm.org/viewvc/llvm-project?rev=134623&view=rev Log: Fix wording in docstring. Modified: lldb/trunk/include/lldb/API/SBDebugger.h Modified: lldb/trunk/include/lldb/API/SBDebugger.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBDebugger.h?rev=134623&r1=134622&r2=134623&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBDebugger.h (original) +++ lldb/trunk/include/lldb/API/SBDebugger.h Thu Jul 7 13:50:45 2011 @@ -20,7 +20,7 @@ "SBDebugger is the primordial object that creates SBTargets and provides access to them. It also manages the overall debugging experiences. -For example (in example/disasm.py), +For example (from example/disasm.py), import lldb import os From johnny.chen at apple.com Thu Jul 7 15:23:22 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 20:23:22 -0000 Subject: [Lldb-commits] [lldb] r134632 - /lldb/trunk/include/lldb/API/SBValueList.h Message-ID: <20110707202322.C62EC2A6C12C@llvm.org> Author: johnny Date: Thu Jul 7 15:23:22 2011 New Revision: 134632 URL: http://llvm.org/viewvc/llvm-project?rev=134632&view=rev Log: Add docstrings for SBValueList with example usage. Modified: lldb/trunk/include/lldb/API/SBValueList.h Modified: lldb/trunk/include/lldb/API/SBValueList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValueList.h?rev=134632&r1=134631&r2=134632&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBValueList.h (original) +++ lldb/trunk/include/lldb/API/SBValueList.h Thu Jul 7 15:23:22 2011 @@ -14,8 +14,71 @@ namespace lldb { +#ifdef SWIG +%feature("docstring", +"Represents a collection of SBValues. Both SBFrame's GetVariables() and +GetRegisters() return a SBValueList. + +For example (from test/lldbutil.py), + +def get_registers(frame, kind): + '''Returns the registers given the frame and the kind of registers desired. + + Returns None if there's no such kind. + ''' + registerSet = frame.GetRegisters() # Return type of SBValueList. + for value in registerSet: + if kind.lower() in value.GetName().lower(): + return value + + return None + +def get_GPRs(frame): + '''Returns the general purpose registers of the frame as an SBValue. + + The returned SBValue object is iterable. An example: + ... + from lldbutil import get_GPRs + regs = get_GPRs(frame) + for reg in regs: + print '%s => %s' % (reg.GetName(), reg.GetValue()) + ... + ''' + return get_registers(frame, 'general purpose') + +def get_FPRs(frame): + '''Returns the floating point registers of the frame as an SBValue. + + The returned SBValue object is iterable. An example: + ... + from lldbutil import get_FPRs + regs = get_FPRs(frame) + for reg in regs: + print '%s => %s' % (reg.GetName(), reg.GetValue()) + ... + ''' + return get_registers(frame, 'floating point') + +def get_ESRs(frame): + '''Returns the exception state registers of the frame as an SBValue. + + The returned SBValue object is iterable. An example: + ... + from lldbutil import get_ESRs + regs = get_ESRs(frame) + for reg in regs: + print '%s => %s' % (reg.GetName(), reg.GetValue()) + ... + ''' + return get_registers(frame, 'exception state') +" + ) SBValueList; +#endif class SBValueList { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: SBValueList (); From johnny.chen at apple.com Thu Jul 7 15:46:24 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 20:46:24 -0000 Subject: [Lldb-commits] [lldb] r134636 - in /lldb/trunk: include/lldb/API/SBValue.h source/API/SBValue.cpp Message-ID: <20110707204624.2BED72A6C12C@llvm.org> Author: johnny Date: Thu Jul 7 15:46:23 2011 New Revision: 134636 URL: http://llvm.org/viewvc/llvm-project?rev=134636&view=rev Log: Add SBValue::GetID() member method call API. Modified: lldb/trunk/include/lldb/API/SBValue.h lldb/trunk/source/API/SBValue.cpp Modified: lldb/trunk/include/lldb/API/SBValue.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBValue.h?rev=134636&r1=134635&r2=134636&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBValue.h (original) +++ lldb/trunk/include/lldb/API/SBValue.h Thu Jul 7 15:46:23 2011 @@ -44,6 +44,9 @@ SBError GetError(); + lldb::user_id_t + GetID (); + const char * GetName(); Modified: lldb/trunk/source/API/SBValue.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBValue.cpp?rev=134636&r1=134635&r2=134636&view=diff ============================================================================== --- lldb/trunk/source/API/SBValue.cpp (original) +++ lldb/trunk/source/API/SBValue.cpp Thu Jul 7 15:46:23 2011 @@ -82,6 +82,14 @@ return sb_error; } +user_id_t +SBValue::GetID() +{ + if (m_opaque_sp) + return m_opaque_sp->GetID(); + return LLDB_INVALID_UID; +} + const char * SBValue::GetName() { From johnny.chen at apple.com Thu Jul 7 17:22:51 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 22:22:51 -0000 Subject: [Lldb-commits] [lldb] r134646 - /lldb/trunk/test/python_api/target/TestTargetAPI.py Message-ID: <20110707222251.40E9B2A6C12C@llvm.org> Author: johnny Date: Thu Jul 7 17:22:51 2011 New Revision: 134646 URL: http://llvm.org/viewvc/llvm-project?rev=134646&view=rev Log: Add test cases to exercise the SBTarget.FindFunctions() API. Modified: lldb/trunk/test/python_api/target/TestTargetAPI.py Modified: lldb/trunk/test/python_api/target/TestTargetAPI.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/target/TestTargetAPI.py?rev=134646&r1=134645&r2=134646&view=diff ============================================================================== --- lldb/trunk/test/python_api/target/TestTargetAPI.py (original) +++ lldb/trunk/test/python_api/target/TestTargetAPI.py Thu Jul 7 17:22:51 2011 @@ -33,6 +33,23 @@ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") @python_api_test + def test_find_functions_with_dsym(self): + """Exercise SBTaget.FindFunctions() API.""" + d = {'EXE': 'a.out'} + self.buildDsym(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.find_functions('a.out') + + @python_api_test + def test_find_functions_with_dwarf(self): + """Exercise SBTarget.FindFunctions() API.""" + d = {'EXE': 'b.out'} + self.buildDwarf(dictionary=d) + self.setTearDownCleanup(dictionary=d) + self.find_functions('b.out') + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test def test_get_description_with_dsym(self): """Exercise SBTaget.GetDescription() API.""" self.buildDsym() @@ -88,6 +105,7 @@ value_list = target.FindGlobalVariables('my_global_var_of_char_type', 3) self.assertTrue(value_list.GetSize() == 1) my_global_var = value_list.GetValueAtIndex(0) + self.assertTrue(my_global_var) self.expect(my_global_var.GetName(), exe=False, startstr = "my_global_var_of_char_type") self.expect(my_global_var.GetTypeName(), exe=False, @@ -103,6 +121,21 @@ self.assertTrue(value_list.GetValueAtIndex(0).GetValue() == "'X'") break + def find_functions(self, exe_name): + """Exercise SBTaget.FindFunctions() API.""" + exe = os.path.join(os.getcwd(), exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + list = lldb.SBSymbolContextList() + num = target.FindFunctions('c', lldb.eFunctionNameTypeAuto, False, list) + self.assertTrue(num == 1 and list.GetSize() == 1) + + for sc in list: + self.assertTrue(sc.GetSymbol().GetName() == 'c') + def get_description(self): """Exercise SBTaget.GetDescription() API.""" exe = os.path.join(os.getcwd(), "a.out") From johnny.chen at apple.com Thu Jul 7 17:45:54 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 22:45:54 -0000 Subject: [Lldb-commits] [lldb] r134651 - /lldb/trunk/test/python_api/target/TestTargetAPI.py Message-ID: <20110707224554.4133F2A6C12F@llvm.org> Author: johnny Date: Thu Jul 7 17:45:54 2011 New Revision: 134651 URL: http://llvm.org/viewvc/llvm-project?rev=134651&view=rev Log: Add assert to check the SBModule of SBSymbolContextList returned from SBTarget.FindFunctions(). Modified: lldb/trunk/test/python_api/target/TestTargetAPI.py Modified: lldb/trunk/test/python_api/target/TestTargetAPI.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/target/TestTargetAPI.py?rev=134651&r1=134650&r2=134651&view=diff ============================================================================== --- lldb/trunk/test/python_api/target/TestTargetAPI.py (original) +++ lldb/trunk/test/python_api/target/TestTargetAPI.py Thu Jul 7 17:45:54 2011 @@ -134,6 +134,7 @@ self.assertTrue(num == 1 and list.GetSize() == 1) for sc in list: + self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name) self.assertTrue(sc.GetSymbol().GetName() == 'c') def get_description(self): From johnny.chen at apple.com Thu Jul 7 17:48:47 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 22:48:47 -0000 Subject: [Lldb-commits] [lldb] r134652 - in /lldb/trunk/include/lldb/API: SBSymbol.h SBSymbolContextList.h Message-ID: <20110707224847.1BD662A6C12F@llvm.org> Author: johnny Date: Thu Jul 7 17:48:46 2011 New Revision: 134652 URL: http://llvm.org/viewvc/llvm-project?rev=134652&view=rev Log: Add docstrings for SBSymbolContextList with example usage. Modified: lldb/trunk/include/lldb/API/SBSymbol.h lldb/trunk/include/lldb/API/SBSymbolContextList.h Modified: lldb/trunk/include/lldb/API/SBSymbol.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBSymbol.h?rev=134652&r1=134651&r2=134652&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBSymbol.h (original) +++ lldb/trunk/include/lldb/API/SBSymbol.h Thu Jul 7 17:48:46 2011 @@ -19,7 +19,7 @@ #ifdef SWIG %feature("docstring", - "Represents the symbol associated with a stack frame." + "Represents the symbol possibly associated with a stack frame." ) SBSymbol; #endif class SBSymbol Modified: lldb/trunk/include/lldb/API/SBSymbolContextList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBSymbolContextList.h?rev=134652&r1=134651&r2=134652&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBSymbolContextList.h (original) +++ lldb/trunk/include/lldb/API/SBSymbolContextList.h Thu Jul 7 17:48:46 2011 @@ -15,8 +15,35 @@ namespace lldb { +#ifdef SWIG +%feature("docstring", +"Represents a list of symbol context object. See also SBSymbolContext. + +For example (from test/python_api/target/TestTargetAPI.py), + + def find_functions(self, exe_name): + '''Exercise SBTaget.FindFunctions() API.''' + exe = os.path.join(os.getcwd(), exe_name) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + list = lldb.SBSymbolContextList() + num = target.FindFunctions('c', lldb.eFunctionNameTypeAuto, False, list) + self.assertTrue(num == 1 and list.GetSize() == 1) + + for sc in list: + self.assertTrue(sc.GetModule().GetFileSpec().GetFilename() == exe_name) + self.assertTrue(sc.GetSymbol().GetName() == 'c') +" + ) SBSymbolContextList; +#endif class SBSymbolContextList { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: SBSymbolContextList (); From scallanan at apple.com Thu Jul 7 18:05:43 2011 From: scallanan at apple.com (Sean Callanan) Date: Thu, 07 Jul 2011 23:05:43 -0000 Subject: [Lldb-commits] [lldb] r134656 - /lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Message-ID: <20110707230543.7D1CA2A6C12C@llvm.org> Author: spyffe Date: Thu Jul 7 18:05:43 2011 New Revision: 134656 URL: http://llvm.org/viewvc/llvm-project?rev=134656&view=rev Log: Added checks to the expresssion parser which make searching for variables and symbols in the target more robust. These checks prevent variables from being reported as existing if they cannot actually be evaluated in the current context. Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=134656&r1=134655&r2=134656&view=diff ============================================================================== --- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original) +++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Thu Jul 7 18:05:43 2011 @@ -552,6 +552,9 @@ else return false; + if (!func_so_addr || !func_so_addr->IsValid()) + return false; + func_addr = func_so_addr->GetCallableLoadAddress (m_parser_vars->m_exe_ctx->target); return true; @@ -573,6 +576,10 @@ sc_list.GetContextAtIndex(i, sym_ctx); const Address *sym_address = &sym_ctx.symbol->GetAddressRangeRef().GetBaseAddress(); + + if (!sym_address || !sym_address->IsValid()) + return LLDB_INVALID_ADDRESS; + if (sym_address) { switch (sym_ctx.symbol->GetType()) @@ -1261,7 +1268,7 @@ NULL)); } else if (sym) - { + { location_value.reset(new Value); addr_t location_load_addr = GetSymbolAddress(*exe_ctx.target, name); @@ -1591,6 +1598,11 @@ var_sp = program_globals.GetVariableAtIndex (0); } } + + if (!var_sp || + !var_sp->IsInScope(&frame) || + !var_sp->LocationIsValidForFrame (&frame)) + return lldb::VariableSP(); if (var_sp && type) { From johnny.chen at apple.com Thu Jul 7 18:45:49 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 07 Jul 2011 23:45:49 -0000 Subject: [Lldb-commits] [lldb] r134659 - in /lldb/trunk: include/lldb/API/SBEvent.h test/python_api/default-constructor/sb_event.py Message-ID: <20110707234549.A57CC2A6C12D@llvm.org> Author: johnny Date: Thu Jul 7 18:45:49 2011 New Revision: 134659 URL: http://llvm.org/viewvc/llvm-project?rev=134659&view=rev Log: The Python API does not need SBEvent::BroadcasterMatchesPtr() when SBEvent::BroadcasterMatchesRef() suffices. Modified: lldb/trunk/include/lldb/API/SBEvent.h lldb/trunk/test/python_api/default-constructor/sb_event.py Modified: lldb/trunk/include/lldb/API/SBEvent.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBEvent.h?rev=134659&r1=134658&r2=134659&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBEvent.h (original) +++ lldb/trunk/include/lldb/API/SBEvent.h Thu Jul 7 18:45:49 2011 @@ -49,8 +49,10 @@ lldb::SBBroadcaster GetBroadcaster () const; +#ifndef SWIG bool BroadcasterMatchesPtr (const lldb::SBBroadcaster *broadcaster); +#endif bool BroadcasterMatchesRef (const lldb::SBBroadcaster &broadcaster); Modified: lldb/trunk/test/python_api/default-constructor/sb_event.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/default-constructor/sb_event.py?rev=134659&r1=134658&r2=134659&view=diff ============================================================================== --- lldb/trunk/test/python_api/default-constructor/sb_event.py (original) +++ lldb/trunk/test/python_api/default-constructor/sb_event.py Thu Jul 7 18:45:49 2011 @@ -12,7 +12,6 @@ # Do fuzz testing on the broadcaster obj, it should not crash lldb. import sb_broadcaster sb_broadcaster.fuzz_obj(broadcaster) - obj.BroadcasterMatchesPtr(None) obj.BroadcasterMatchesRef(broadcaster) obj.GetDescription(lldb.SBStream()) obj.Clear() From jmolenda at apple.com Thu Jul 7 19:00:32 2011 From: jmolenda at apple.com (Jason Molenda) Date: Fri, 08 Jul 2011 00:00:32 -0000 Subject: [Lldb-commits] [lldb] r134662 - /lldb/trunk/tools/debugserver/source/debugserver.cpp Message-ID: <20110708000032.B919D2A6C12C@llvm.org> Author: jmolenda Date: Thu Jul 7 19:00:32 2011 New Revision: 134662 URL: http://llvm.org/viewvc/llvm-project?rev=134662&view=rev Log: Handle the possible case where the process launch failed but we don't have an error message. Modified: lldb/trunk/tools/debugserver/source/debugserver.cpp Modified: lldb/trunk/tools/debugserver/source/debugserver.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/debugserver.cpp?rev=134662&r1=134661&r2=134662&view=diff ============================================================================== --- lldb/trunk/tools/debugserver/source/debugserver.cpp (original) +++ lldb/trunk/tools/debugserver/source/debugserver.cpp Thu Jul 7 19:00:32 2011 @@ -228,12 +228,18 @@ g_pid = pid; - if (pid == INVALID_NUB_PROCESS && strlen(launch_err_str) > 0) + if (pid == INVALID_NUB_PROCESS && strlen (launch_err_str) > 0) { DNBLogThreaded ("%s DNBProcessLaunch() returned error: '%s'", __FUNCTION__, launch_err_str); ctx.LaunchStatus().SetError(-1, DNBError::Generic); ctx.LaunchStatus().SetErrorString(launch_err_str); } + else if (pid == INVALID_NUB_PROCESS) + { + DNBLogThreaded ("%s DNBProcessLaunch() failed to launch process, unknown failure", __FUNCTION__); + ctx.LaunchStatus().SetError(-1, DNBError::Generic); + ctx.LaunchStatus().SetErrorString(launch_err_str); + } else { ctx.LaunchStatus().Clear(); From jmolenda at apple.com Thu Jul 7 19:38:03 2011 From: jmolenda at apple.com (Jason Molenda) Date: Fri, 08 Jul 2011 00:38:03 -0000 Subject: [Lldb-commits] [lldb] r134669 - in /lldb/trunk/source: Commands/CommandCompletions.cpp Core/DataBufferMemoryMap.cpp Message-ID: <20110708003803.D0EAA2A6C12C@llvm.org> Author: jmolenda Date: Thu Jul 7 19:38:03 2011 New Revision: 134669 URL: http://llvm.org/viewvc/llvm-project?rev=134669&view=rev Log: Switch to using the S_ISDIR and S_ISREG sys/stat.h macros in CommandCompletions.cpp and DataBufferMemoryMap.cpp. The file type part of the st_mode struct member is not a bitmask. Modified: lldb/trunk/source/Commands/CommandCompletions.cpp lldb/trunk/source/Core/DataBufferMemoryMap.cpp Modified: lldb/trunk/source/Commands/CommandCompletions.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandCompletions.cpp?rev=134669&r1=134668&r2=134669&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandCompletions.cpp (original) +++ lldb/trunk/source/Commands/CommandCompletions.cpp Thu Jul 7 19:38:03 2011 @@ -272,7 +272,7 @@ else if (dirent_buf->d_type & DT_LNK) { struct stat stat_buf; - if ((stat(partial_name_copy, &stat_buf) == 0) && (stat_buf.st_mode & S_IFDIR)) + if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) isa_directory = true; } Modified: lldb/trunk/source/Core/DataBufferMemoryMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/DataBufferMemoryMap.cpp?rev=134669&r1=134668&r2=134669&view=diff ============================================================================== --- lldb/trunk/source/Core/DataBufferMemoryMap.cpp (original) +++ lldb/trunk/source/Core/DataBufferMemoryMap.cpp Thu Jul 7 19:38:03 2011 @@ -158,7 +158,7 @@ struct stat stat; if (::fstat(fd, &stat) == 0) { - if ((stat.st_mode & S_IFREG) && (stat.st_size > offset)) + if (S_ISREG(stat.st_mode) && (stat.st_size > offset)) { const size_t max_bytes_available = stat.st_size - offset; if (length == SIZE_MAX) From scallanan at apple.com Thu Jul 7 19:39:14 2011 From: scallanan at apple.com (Sean Callanan) Date: Fri, 08 Jul 2011 00:39:14 -0000 Subject: [Lldb-commits] [lldb] r134670 - in /lldb/trunk/source/Expression: ASTResultSynthesizer.cpp ClangExpressionDeclMap.cpp IRDynamicChecks.cpp IRForTarget.cpp Message-ID: <20110708003914.5344A2A6C12C@llvm.org> Author: spyffe Date: Thu Jul 7 19:39:14 2011 New Revision: 134670 URL: http://llvm.org/viewvc/llvm-project?rev=134670&view=rev Log: Audited the expression parser to find uninitialized pointers. Some of the spots are obviously initialized later, but it's better just to NULL the pointers out at initialization to make the code more robust when exposed to later changes. Modified: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp lldb/trunk/source/Expression/IRDynamicChecks.cpp lldb/trunk/source/Expression/IRForTarget.cpp Modified: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTResultSynthesizer.cpp?rev=134670&r1=134669&r2=134670&view=diff ============================================================================== --- lldb/trunk/source/Expression/ASTResultSynthesizer.cpp (original) +++ lldb/trunk/source/Expression/ASTResultSynthesizer.cpp Thu Jul 7 19:39:14 2011 @@ -309,7 +309,7 @@ log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); } - clang::VarDecl *result_decl; + clang::VarDecl *result_decl = NULL; if (is_lvalue) { Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=134670&r1=134669&r2=134670&view=diff ============================================================================== --- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original) +++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Thu Jul 7 19:39:14 2011 @@ -1684,8 +1684,8 @@ if (const NamespaceDecl *namespace_decl = dyn_cast(context_decl)) { - Decl *original_decl; - ASTContext *original_ctx; + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; if (log) log->Printf("Resolving the containing context's origin..."); @@ -1717,7 +1717,7 @@ DeclContextLookupConstResult original_lookup_result = original_ctx->getExternalSource()->FindExternalVisibleDeclsByName(original_decl_context, context.m_decl_name); - NamedDecl *const *iter; + NamedDecl *const *iter = NULL; for (iter = original_lookup_result.first; iter != original_lookup_result.second; @@ -1866,7 +1866,7 @@ m_struct_vars->m_object_pointer_type = this_user_type; - void *pointer_target_type; + void *pointer_target_type = NULL; if (!ClangASTContext::IsPointerType(this_user_type.GetOpaqueQualType(), &pointer_target_type)) @@ -1915,7 +1915,7 @@ m_struct_vars->m_object_pointer_type = self_user_type; - void *pointer_target_type; + void *pointer_target_type = NULL; if (!ClangASTContext::IsPointerType(self_user_type.GetOpaqueQualType(), &pointer_target_type)) @@ -2075,7 +2075,7 @@ return NULL; } - void *type_to_use; + void *type_to_use = NULL; if (parser_ast_context) { @@ -2395,9 +2395,9 @@ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - NamedDecl *fun_decl; + NamedDecl *fun_decl = NULL; std::auto_ptr fun_location(new Value); - const Address *fun_address; + const Address *fun_address = NULL; // only valid for Functions, not for Symbols void *fun_opaque_type = NULL; Modified: lldb/trunk/source/Expression/IRDynamicChecks.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRDynamicChecks.cpp?rev=134670&r1=134669&r2=134670&view=diff ============================================================================== --- lldb/trunk/source/Expression/IRDynamicChecks.cpp (original) +++ lldb/trunk/source/Expression/IRDynamicChecks.cpp Thu Jul 7 19:39:14 2011 @@ -314,7 +314,7 @@ if (!m_valid_pointer_check_func) m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress()); - llvm::Value *dereferenced_ptr; + llvm::Value *dereferenced_ptr = NULL; if (llvm::LoadInst *li = dyn_cast (inst)) dereferenced_ptr = li->getPointerOperand(); @@ -382,7 +382,7 @@ if (!m_objc_object_check_func) m_objc_object_check_func = BuildPointerValidatorFunc(m_checker_functions.m_objc_object_check->StartAddress()); - llvm::Value *target_object; + llvm::Value *target_object = NULL; // id objc_msgSend(id theReceiver, SEL theSelector, ...) Modified: lldb/trunk/source/Expression/IRForTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=134670&r1=134669&r2=134670&view=diff ============================================================================== --- lldb/trunk/source/Expression/IRForTarget.cpp (original) +++ lldb/trunk/source/Expression/IRForTarget.cpp Thu Jul 7 19:39:14 2011 @@ -641,12 +641,10 @@ m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); } - ConstantArray *string_array; + ConstantArray *string_array = NULL; if (cstr) string_array = dyn_cast(cstr->getInitializer()); - else - string_array = NULL; SmallVector CFSCWB_arguments; @@ -1266,7 +1264,7 @@ } clang::QualType qual_type; - const Type *value_type; + const Type *value_type = NULL; if (name[0] == '$') { @@ -1493,7 +1491,7 @@ if (log) log->Printf("Found \"%s\" at 0x%llx", str.GetCString(), fun_addr); - Value *fun_addr_ptr; + Value *fun_addr_ptr = NULL; if (!fun_value_ptr || !*fun_value_ptr) { @@ -1806,12 +1804,12 @@ static bool isGuardVariableRef(Value *V) { - Constant *Old; + Constant *Old = NULL; if (!(Old = dyn_cast(V))) return false; - ConstantExpr *CE; + ConstantExpr *CE = NULL; if ((CE = dyn_cast(V))) { @@ -2121,8 +2119,8 @@ for (element_index = 0; element_index < num_elements; ++element_index) { - const clang::NamedDecl *decl; - Value *value; + const clang::NamedDecl *decl = NULL; + Value *value = NULL; off_t offset; lldb_private::ConstString name; @@ -2144,7 +2142,7 @@ ConstantInt *offset_int(ConstantInt::getSigned(offset_type, offset)); GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument, offset_int, "", FirstEntryInstruction); - Value *replacement; + Value *replacement = NULL; // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result // variable is an rvalue, we have to synthesize a dereference of the appropriate structure From gclayton at apple.com Thu Jul 7 19:48:10 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 00:48:10 -0000 Subject: [Lldb-commits] [lldb] r134672 - in /lldb/trunk: include/lldb/Target/Target.h lldb.xcodeproj/project.pbxproj source/Plugins/DynamicLoader/MacOSX-Kernel/ source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile source/Target/Target.cpp Message-ID: <20110708004810.1F4092A6C12C@llvm.org> Author: gclayton Date: Thu Jul 7 19:48:09 2011 New Revision: 134672 URL: http://llvm.org/viewvc/llvm-project?rev=134672&view=rev Log: Added the start of the darwin dynamic loader plug-in. It isn't hooked up to be detected yet, but most of the initial code is there and needs to be debugged more. Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile Modified: lldb/trunk/include/lldb/Target/Target.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Target/Target.cpp Modified: lldb/trunk/include/lldb/Target/Target.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=134672&r1=134671&r2=134672&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/Target.h (original) +++ lldb/trunk/include/lldb/Target/Target.h Thu Jul 7 19:48:09 2011 @@ -474,6 +474,32 @@ } + //------------------------------------------------------------------ + /// Load a module in this target by at the section file addresses + /// with an optional constant slide applied to each section. + /// + /// This function will load all top level sections at their file + /// addresses and apply an optional constant slide amount to each + /// section. This can be used to easily load a module at the same + /// addresses that are contained in the object file (trust that + /// the addresses in an object file are the correct load addresses). + /// + /// @param[in] module + /// The module to load. + /// + /// @param[in] slide + /// A constant slide to add to each file address as each section + /// is being loaded. + /// + /// @return + /// \b true if loading the module at the specified address + /// causes a section to be loaded when it previously wasn't, or + /// if a section changes load address. Returns \b false if + /// the sections were all already loaded at these addresses. + //------------------------------------------------------------------ + bool + LoadModuleWithSlide (Module *module, lldb::addr_t slide); + static Target * GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr, const SymbolContext *sc_ptr); Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134672&r1=134671&r2=134672&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Jul 7 19:48:09 2011 @@ -381,6 +381,7 @@ 26DE20651161904E00A093E2 /* SBSymbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE20641161904E00A093E2 /* SBSymbol.cpp */; }; 26ECA04313665FED008D1F18 /* ARM_DWARF_Registers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */; }; 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */; }; + 26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F4214113C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp */; }; 26F5C27710F3D9E4009D5894 /* Driver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27310F3D9E4009D5894 /* Driver.cpp */; }; 26F5C27810F3D9E4009D5894 /* IOChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F5C27510F3D9E4009D5894 /* IOChannel.cpp */; }; 26F5C32510F3DF23009D5894 /* libpython.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C32410F3DF23009D5894 /* libpython.dylib */; }; @@ -1051,6 +1052,8 @@ 26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ARM_DWARF_Registers.cpp; path = source/Utility/ARM_DWARF_Registers.cpp; sourceTree = ""; }; 26ED3D6C13C563810017D45E /* OptionGroupVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupVariable.cpp; path = source/Interpreter/OptionGroupVariable.cpp; sourceTree = ""; }; 26ED3D6F13C5638A0017D45E /* OptionGroupVariable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupVariable.h; path = include/lldb/Interpreter/OptionGroupVariable.h; sourceTree = ""; }; + 26F4214113C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderMacOSXKernel.cpp; sourceTree = ""; }; + 26F4214213C6515B00E04E5E /* DynamicLoaderMacOSXKernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderMacOSXKernel.h; sourceTree = ""; }; 26F5C26A10F3D9A4009D5894 /* lldb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = lldb; sourceTree = BUILT_PRODUCTS_DIR; }; 26F5C27210F3D9E4009D5894 /* lldb-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-Info.plist"; path = "tools/driver/lldb-Info.plist"; sourceTree = ""; }; 26F5C27310F3D9E4009D5894 /* Driver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Driver.cpp; path = tools/driver/Driver.cpp; sourceTree = ""; }; @@ -1407,6 +1410,7 @@ isa = PBXGroup; children = ( 260C897910F57C5600BB2B04 /* MacOSX-DYLD */, + 26F4214013C6515B00E04E5E /* MacOSX-Kernel */, 268A683C1321B505000E3FB8 /* Static */, ); path = DynamicLoader; @@ -2473,6 +2477,15 @@ name = "lldb-platform"; sourceTree = ""; }; + 26F4214013C6515B00E04E5E /* MacOSX-Kernel */ = { + isa = PBXGroup; + children = ( + 26F4214113C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp */, + 26F4214213C6515B00E04E5E /* DynamicLoaderMacOSXKernel.h */, + ); + path = "MacOSX-Kernel"; + sourceTree = ""; + }; 26F5C22410F3D950009D5894 /* Tools */ = { isa = PBXGroup; children = ( @@ -3251,6 +3264,7 @@ 49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */, 9467E65213C3D97600B3B6F3 /* TypeHierarchyNavigator.cpp in Sources */, 26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */, + 26F4214413C6515B00E04E5E /* DynamicLoaderMacOSXKernel.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp?rev=134672&view=auto ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp (added) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Thu Jul 7 19:48:09 2011 @@ -0,0 +1,1232 @@ +//===-- DynamicLoaderMacOSXKernel.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/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/State.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" +#include "lldb/Target/StackFrame.h" + +#include "DynamicLoaderMacOSXKernel.h" + +//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN +#ifdef ENABLE_DEBUG_PRINTF +#include +#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else +#define DEBUG_PRINTF(fmt, ...) +#endif + +using namespace lldb; +using namespace lldb_private; + +/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here. +/// I am putting it here so I can invoke it in the Trampoline code here, but +/// it should be moved to the ObjC Runtime support when it is set up. + + +//---------------------------------------------------------------------- +// Create an instance of this class. This function is filled into +// the plugin info class that gets handed out by the plugin factory and +// allows the lldb to instantiate an instance of this class. +//---------------------------------------------------------------------- +DynamicLoader * +DynamicLoaderMacOSXKernel::CreateInstance (Process* process, bool force) +{ + bool create = force; + if (!create) + { + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); + if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple) + create = true; + } + + if (create) + return new DynamicLoaderMacOSXKernel (process); + return NULL; +} + +//---------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------- +DynamicLoaderMacOSXKernel::DynamicLoaderMacOSXKernel (Process* process) : + DynamicLoader(process), + m_kernel(), + m_kext_summary_header_addr (LLDB_INVALID_ADDRESS), + m_kext_summary_header (), + m_kext_summary_header_stop_id (0), + m_break_id (LLDB_INVALID_BREAK_ID), + m_kext_summaries(), + m_kext_summaries_stop_id (UINT32_MAX), + m_mutex(Mutex::eMutexTypeRecursive), + m_notification_callbacks () +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +DynamicLoaderMacOSXKernel::~DynamicLoaderMacOSXKernel() +{ + Clear(true); +} + +//------------------------------------------------------------------ +/// Called after attaching a process. +/// +/// Allow DynamicLoader plug-ins to execute some code after +/// attaching to a process. +//------------------------------------------------------------------ +void +DynamicLoaderMacOSXKernel::DidAttach () +{ + PrivateInitialize(m_process); + LoadKernelModule(); + SetNotificationBreakpoint (); +} + +//------------------------------------------------------------------ +/// Called after attaching a process. +/// +/// Allow DynamicLoader plug-ins to execute some code after +/// attaching to a process. +//------------------------------------------------------------------ +void +DynamicLoaderMacOSXKernel::DidLaunch () +{ + PrivateInitialize(m_process); + LoadKernelModule(); + SetNotificationBreakpoint (); +} + + +//---------------------------------------------------------------------- +// Clear out the state of this class. +//---------------------------------------------------------------------- +void +DynamicLoaderMacOSXKernel::Clear (bool clear_process) +{ + Mutex::Locker locker(m_mutex); + + if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) + m_process->ClearBreakpointSiteByID(m_break_id); + + if (clear_process) + m_process = NULL; + m_kernel.Clear(false); + m_kext_summary_header_addr = LLDB_INVALID_ADDRESS; + m_kext_summaries.clear(); + m_kext_summaries_stop_id = 0; + m_break_id = LLDB_INVALID_BREAK_ID; +} + +//---------------------------------------------------------------------- +// Check if we have found DYLD yet +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOSXKernel::DidSetNotificationBreakpoint() const +{ + return LLDB_BREAK_ID_IS_VALID (m_break_id); +} + +//---------------------------------------------------------------------- +// Load the kernel module and initialize the "m_kernel" member. Return +// true _only_ if the kernel is loaded the first time through (subsequent +// calls to this function should return false after the kernel has been +// already loaded). +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOSXKernel::LoadKernelModule() +{ + if (m_kext_summary_header_addr == LLDB_INVALID_ADDRESS) + { + m_kernel.Clear(false); + m_kernel.module_sp = m_process->GetTarget().GetExecutableModule(); + if (m_kernel.module_sp) + { + static ConstString mach_header_name ("_mh_execute_header"); + const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute); + if (symbol) + { + m_kernel.address = symbol->GetValue().GetFileAddress(); + DataExtractor data; // Load command data + if (ReadMachHeader (m_kernel.address, &m_kernel.header, &data)) + { + if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) + { + if (ParseLoadCommands (data, m_kernel)) + UpdateImageLoadAddress (m_kernel); + + // Update all image infos + ReadAllKextSummaries (false); + return true; + } + } + else + { + m_kernel.Clear(false); + } + return false; + } + } + } + return false; +} + +bool +DynamicLoaderMacOSXKernel::FindTargetModule (OSKextLoadedKextSummary &image_info, bool can_create, bool *did_create_ptr) +{ + if (did_create_ptr) + *did_create_ptr = false; + + const bool image_info_uuid_is_valid = image_info.uuid.IsValid(); + + if (image_info.module_sp) + { + if (image_info_uuid_is_valid) + { + if (image_info.module_sp->GetUUID() == image_info.uuid) + return true; + else + image_info.module_sp.reset(); + } + else + return true; + } + + ModuleList &target_images = m_process->GetTarget().GetImages(); + if (image_info_uuid_is_valid) + image_info.module_sp = target_images.FindModule(image_info.uuid); + + if (image_info.module_sp) + return true; + + ArchSpec arch (image_info.GetArchitecture ()); + if (can_create) + { + if (image_info_uuid_is_valid) + { + image_info.module_sp = m_process->GetTarget().GetSharedModule (FileSpec(), + arch, + &image_info.uuid); + if (did_create_ptr) + *did_create_ptr = image_info.module_sp; + } + } + return image_info.module_sp; +} + +bool +DynamicLoaderMacOSXKernel::UpdateCommPageLoadAddress(Module *module) +{ + bool changed = false; + if (module) + { + ObjectFile *image_object_file = module->GetObjectFile(); + if (image_object_file) + { + SectionList *section_list = image_object_file->GetSectionList (); + if (section_list) + { + uint32_t num_sections = section_list->GetSize(); + for (uint32_t i=0; iGetSectionAtIndex (i).get(); + if (section) + { + const addr_t new_section_load_addr = section->GetFileAddress (); + const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section); + if (old_section_load_addr == LLDB_INVALID_ADDRESS || + old_section_load_addr != new_section_load_addr) + { + if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section, section->GetFileAddress ())) + changed = true; + } + } + } + } + } + } + return changed; +} + +//---------------------------------------------------------------------- +// Update the load addresses for all segments in MODULE using the +// updated INFO that is passed in. +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOSXKernel::UpdateImageLoadAddress (OSKextLoadedKextSummary& info) +{ + Module *module = info.module_sp.get(); + bool changed = false; + if (module) + { + ObjectFile *image_object_file = module->GetObjectFile(); + if (image_object_file) + { + SectionList *section_list = image_object_file->GetSectionList (); + if (section_list) + { + // We now know the slide amount, so go through all sections + // and update the load addresses with the correct values. + uint32_t num_segments = info.segments.size(); + for (uint32_t i=0; iFindSectionByName(info.segments[i].name)); + const addr_t new_section_load_addr = info.segments[i].vmaddr; + if (section_sp) + { + const addr_t old_section_load_addr = m_process->GetTarget().GetSectionLoadList().GetSectionLoadAddress (section_sp.get()); + if (old_section_load_addr == LLDB_INVALID_ADDRESS || + old_section_load_addr != new_section_load_addr) + { + if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), new_section_load_addr)) + changed = true; + } + } + else + { + fprintf (stderr, + "warning: unable to find and load segment named '%s' at 0x%llx in '%s/%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + (uint64_t)new_section_load_addr, + image_object_file->GetFileSpec().GetDirectory().AsCString(), + image_object_file->GetFileSpec().GetFilename().AsCString()); + } + } + } + } + } + return changed; +} + +//---------------------------------------------------------------------- +// Update the load addresses for all segments in MODULE using the +// updated INFO that is passed in. +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOSXKernel::UnloadImageLoadAddress (OSKextLoadedKextSummary& info) +{ + Module *module = info.module_sp.get(); + bool changed = false; + if (module) + { + ObjectFile *image_object_file = module->GetObjectFile(); + if (image_object_file) + { + SectionList *section_list = image_object_file->GetSectionList (); + if (section_list) + { + uint32_t num_segments = info.segments.size(); + for (uint32_t i=0; iFindSectionByName(info.segments[i].name)); + if (section_sp) + { + const addr_t old_section_load_addr = info.segments[i].vmaddr; + if (m_process->GetTarget().GetSectionLoadList().SetSectionUnloaded (section_sp.get(), old_section_load_addr)) + changed = true; + } + else + { + fprintf (stderr, + "warning: unable to find and unload segment named '%s' in '%s/%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + image_object_file->GetFileSpec().GetDirectory().AsCString(), + image_object_file->GetFileSpec().GetFilename().AsCString()); + } + } + } + } + } + return changed; +} + + +//---------------------------------------------------------------------- +// Static callback function that gets called when our DYLD notification +// breakpoint gets hit. We update all of our image infos and then +// let our super class DynamicLoader class decide if we should stop +// or not (based on global preference). +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOSXKernel::NotifyBreakpointHit (void *baton, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) +{ + // Let the event know that the images have changed + // DYLD passes three arguments to the notification breakpoint. + // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing + // Arg2: uint32_t infoCount - Number of shared libraries added + // Arg3: dyld_image_info info[] - Array of structs of the form: + // const struct mach_header *imageLoadAddress + // const char *imageFilePath + // uintptr_t imageFileModDate (a time_t) + + DynamicLoaderMacOSXKernel* dyld_instance = (DynamicLoaderMacOSXKernel*) baton; + + // First step is to see if we've already initialized the all image infos. If we haven't then this function + // will do so and return true. In the course of initializing the all_image_infos it will read the complete + // current state, so we don't need to figure out what has changed from the data passed in to us. + + if (!dyld_instance->ReadAllKextSummaries(false)) + { + Process *process = context->exe_ctx.process; + const lldb::ABISP &abi = process->GetABI(); + if (abi != NULL) + { + // Build up the value array to store the three arguments given above, then get the values from the ABI: + + ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); + ValueList argument_values; + Value input_value; + + void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); + void *clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32); + input_value.SetValueType (Value::eValueTypeScalar); + input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type); + argument_values.PushValue(input_value); + argument_values.PushValue(input_value); + input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type); + argument_values.PushValue (input_value); + + if (abi->GetArgumentValues (*context->exe_ctx.thread, argument_values)) + { + uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1); + if (dyld_mode != -1) + { + // Okay the mode was right, now get the number of elements, and the array of new elements... + uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1); + if (image_infos_count != -1) + { + // Got the number added, now go through the array of added elements, putting out the mach header + // address, and adding the image. + // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do + // all the logging internally. + + lldb::addr_t kext_summary_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(); + if (dyld_mode == 0) + { + // This is add: + dyld_instance->ParseKextSummaries (kext_summary_addr, image_infos_count); + } + else + { + // This is remove: + dyld_instance->RemoveModulesUsingImageInfosAddress (kext_summary_addr, image_infos_count); + } + + } + } + } + } + } + // Return true to stop the target, false to just let the target run + return dyld_instance->GetStopWhenImagesChange(); +} + +bool +DynamicLoaderMacOSXKernel::ReadKextSummaryHeader () +{ + Mutex::Locker locker(m_mutex); + + // the all image infos is already valid for this process stop ID + if (m_process->GetStopID() == m_kext_summaries_stop_id) + return true; + + m_kext_summaries.clear(); + if (m_kext_summary_header_addr != LLDB_INVALID_ADDRESS) + { + const uint32_t addr_size = m_kernel.GetAddressByteSize (); + const ByteOrder byte_order = m_kernel.GetByteOrder(); + Error error; + // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure + // which is currenty 4 uint32_t and a pointer. + uint8_t buf[24]; + DataExtractor data (buf, sizeof(buf), byte_order, addr_size); + const size_t count = 4 * sizeof(uint32_t) + addr_size; + const size_t bytes_read = m_process->ReadMemory (m_kext_summary_header_addr, buf, count, error); + if (bytes_read == count) + { + uint32_t offset = 0; + m_kext_summary_header.version = data.GetU32(&offset); + m_kext_summary_header.entry_size = data.GetU32(&offset); + m_kext_summary_header.entry_count = data.GetU32(&offset); + m_kext_summary_header.reserved = data.GetU32(&offset); + m_kext_summary_header_stop_id = m_process->GetStopID(); + return true; + } + } + return false; +} + + +bool +DynamicLoaderMacOSXKernel::ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count) +{ + OSKextLoadedKextSummary::collection kext_summaries; + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + if (log) + log->Printf ("Adding %d modules.\n"); + + Mutex::Locker locker(m_mutex); + if (m_process->GetStopID() == m_kext_summaries_stop_id) + return true; + + if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries)) + return false; + + for (uint32_t i = 0; i < count; i++) + { + if (!kext_summaries[i].UUIDValid()) + { + DataExtractor data; // Load command data + if (!ReadMachHeader (kext_summaries[i].address, &kext_summaries[i].header, &data)) + continue; + + ParseLoadCommands (data, kext_summaries[i]); + } + } + bool return_value = AddModulesUsingImageInfos (kext_summaries); + m_kext_summaries_stop_id = m_process->GetStopID(); + return return_value; +} + +// Adds the modules in image_infos to m_kext_summaries. +// NB don't call this passing in m_kext_summaries. + +bool +DynamicLoaderMacOSXKernel::AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos) +{ + // Now add these images to the main list. + ModuleList loaded_module_list; + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + + for (uint32_t idx = 0; idx < image_infos.size(); ++idx) + { + if (log) + { + log->Printf ("Adding new image at address=0x%16.16llx.", image_infos[idx].address); + image_infos[idx].PutToLog (log.get()); + } + + m_kext_summaries.push_back(image_infos[idx]); + + if (FindTargetModule (image_infos[idx], true, NULL)) + { + // UpdateImageLoadAddress will return true if any segments + // change load address. We need to check this so we don't + // mention that all loaded shared libraries are newly loaded + // each time we hit out dyld breakpoint since dyld will list all + // shared libraries each time. + if (UpdateImageLoadAddress (image_infos[idx])) + { + loaded_module_list.AppendIfNeeded (image_infos[idx].module_sp); + } + } + } + + if (loaded_module_list.GetSize() > 0) + { + // FIXME: This should really be in the Runtime handlers class, which should get + // called by the target's ModulesDidLoad, but we're doing it all locally for now + // to save time. + // Also, I'm assuming there can be only one libobjc dylib loaded... + + ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); + if (objc_runtime != NULL && !objc_runtime->HasReadObjCLibrary()) + { + size_t num_modules = loaded_module_list.GetSize(); + for (int i = 0; i < num_modules; i++) + { + if (objc_runtime->IsModuleObjCLibrary (loaded_module_list.GetModuleAtIndex (i))) + { + objc_runtime->ReadObjCLibrary (loaded_module_list.GetModuleAtIndex (i)); + break; + } + } + } + if (log) + loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidLoad"); + m_process->GetTarget().ModulesDidLoad (loaded_module_list); + } + return true; +} + +bool +DynamicLoaderMacOSXKernel::RemoveModulesUsingImageInfosAddress (lldb::addr_t kext_summary_addr, uint32_t image_infos_count) +{ + OSKextLoadedKextSummary::collection image_infos; + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + + Mutex::Locker locker(m_mutex); + if (m_process->GetStopID() == m_kext_summaries_stop_id) + return true; + + // First read in the image_infos for the removed modules, and their headers & load commands. + if (!ReadKextSummaries (kext_summary_addr, image_infos_count, image_infos)) + { + if (log) + log->PutCString ("Failed reading image infos array."); + return false; + } + + if (log) + log->Printf ("Removing %d modules.", image_infos_count); + + ModuleList unloaded_module_list; + for (uint32_t idx = 0; idx < image_infos.size(); ++idx) + { + if (log) + { + log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address); + image_infos[idx].PutToLog (log.get()); + } + + // Remove this image_infos from the m_all_image_infos. We do the comparision by address + // rather than by file spec because we can have many modules with the same "file spec" in the + // case that they are modules loaded from memory. + // + // Also copy over the uuid from the old entry to the removed entry so we can + // use it to lookup the module in the module list. + + OSKextLoadedKextSummary::collection::iterator pos, end = m_kext_summaries.end(); + for (pos = m_kext_summaries.begin(); pos != end; pos++) + { + if (image_infos[idx].address == (*pos).address) + { + image_infos[idx].uuid = (*pos).uuid; + + // Add the module from this image_info to the "unloaded_module_list". We'll remove them all at + // one go later on. + + if (FindTargetModule (image_infos[idx], false, NULL)) + { + UnloadImageLoadAddress (image_infos[idx]); + unloaded_module_list.AppendIfNeeded (image_infos[idx].module_sp); + } + else + { + if (log) + { + log->Printf ("Could not find module for unloading info entry:"); + image_infos[idx].PutToLog(log.get()); + } + } + + // Then remove it from the m_kext_summaries: + + m_kext_summaries.erase(pos); + break; + } + } + + if (pos == end) + { + if (log) + { + log->Printf ("Could not find image_info entry for unloading image:"); + image_infos[idx].PutToLog(log.get()); + } + } + } + if (unloaded_module_list.GetSize() > 0) + { + if (log) + { + log->PutCString("Unloaded:"); + unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidUnload"); + } + m_process->GetTarget().ModulesDidUnload (unloaded_module_list); + } + m_kext_summaries_stop_id = m_process->GetStopID(); + return true; +} + +uint32_t +DynamicLoaderMacOSXKernel::ReadKextSummaries (lldb::addr_t kext_summary_addr, + uint32_t image_infos_count, + OSKextLoadedKextSummary::collection &image_infos) +{ + const ByteOrder endian = m_kernel.GetByteOrder(); + const uint32_t addr_size = m_kernel.GetAddressByteSize(); + + image_infos.resize(image_infos_count); + const size_t count = image_infos.size() * m_kext_summary_header.entry_size; + DataBufferHeap data(count, 0); + Error error; + const size_t bytes_read = m_process->ReadMemory (kext_summary_addr, + data.GetBytes(), + data.GetByteSize(), + error); + if (bytes_read == count) + { + uint32_t offset = 0; + DataExtractor extractor (data.GetBytes(), data.GetByteSize(), endian, addr_size); + uint32_t i=0; + for (; i < image_infos.size() && extractor.ValidOffsetForDataOfSize(offset, m_kext_summary_header.entry_size); ++i) + { + const void *name_data = extractor.GetData(&offset, KERNEL_MODULE_MAX_NAME); + if (name_data == NULL) + break; + memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME); + image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16)); + image_infos[i].address = extractor.GetU64(&offset); + image_infos[i].size = extractor.GetU64(&offset); + image_infos[i].version = extractor.GetU64(&offset); + image_infos[i].load_tag = extractor.GetU32(&offset); + image_infos[i].flags = extractor.GetU32(&offset); + image_infos[i].reference_list = extractor.GetU64(&offset); + } + if (i < image_infos.size()) + image_infos.resize(i); + } + else + { + image_infos.clear(); + } + return image_infos.size(); +} + +bool +DynamicLoaderMacOSXKernel::ReadAllKextSummaries (bool force) +{ + LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + + Mutex::Locker locker(m_mutex); + if (!force) + { + if (m_process->GetStopID() == m_kext_summaries_stop_id || m_kext_summaries.size() != 0) + return false; + } + + if (ReadKextSummaryHeader ()) + { + if (m_kext_summary_header.entry_count > 0) + { + if (!ParseKextSummaries (m_kext_summary_header_addr + 16, m_kext_summary_header.entry_count)) + { + DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); + m_kext_summaries.clear(); + } + return true; + } + } + return false; +} + +//---------------------------------------------------------------------- +// Read a mach_header at ADDR into HEADER, and also fill in the load +// command data into LOAD_COMMAND_DATA if it is non-NULL. +// +// Returns true if we succeed, false if we fail for any reason. +//---------------------------------------------------------------------- +bool +DynamicLoaderMacOSXKernel::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data) +{ + DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0); + Error error; + size_t bytes_read = m_process->ReadMemory (addr, + header_bytes.GetBytes(), + header_bytes.GetByteSize(), + error); + if (bytes_read == sizeof(llvm::MachO::mach_header)) + { + uint32_t offset = 0; + ::memset (header, 0, sizeof(header)); + + // Get the magic byte unswapped so we can figure out what we are dealing with + DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4); + header->magic = data.GetU32(&offset); + lldb::addr_t load_cmd_addr = addr; + data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(header->magic)); + switch (header->magic) + { + case llvm::MachO::HeaderMagic32: + case llvm::MachO::HeaderMagic32Swapped: + data.SetAddressByteSize(4); + load_cmd_addr += sizeof(llvm::MachO::mach_header); + break; + + case llvm::MachO::HeaderMagic64: + case llvm::MachO::HeaderMagic64Swapped: + data.SetAddressByteSize(8); + load_cmd_addr += sizeof(llvm::MachO::mach_header_64); + break; + + default: + return false; + } + + // Read the rest of dyld's mach header + if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1)) + { + if (load_command_data == NULL) + return true; // We were able to read the mach_header and weren't asked to read the load command bytes + + DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0)); + + size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr, + load_cmd_data_sp->GetBytes(), + load_cmd_data_sp->GetByteSize(), + error); + + if (load_cmd_bytes_read == header->sizeofcmds) + { + // Set the load command data and also set the correct endian + // swap settings and the correct address size + load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds); + load_command_data->SetByteOrder(data.GetByteOrder()); + load_command_data->SetAddressByteSize(data.GetAddressByteSize()); + return true; // We successfully read the mach_header and the load command data + } + + return false; // We weren't able to read the load command data + } + } + return false; // We failed the read the mach_header +} + + +//---------------------------------------------------------------------- +// Parse the load commands for an image +//---------------------------------------------------------------------- +uint32_t +DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& dylib_info) +{ + uint32_t offset = 0; + uint32_t cmd_idx; + Segment segment; + dylib_info.Clear (true); + + for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) + { + // Clear out any load command specific data from DYLIB_INFO since + // we are about to read it. + + if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command))) + { + llvm::MachO::load_command load_cmd; + uint32_t load_cmd_offset = offset; + load_cmd.cmd = data.GetU32 (&offset); + load_cmd.cmdsize = data.GetU32 (&offset); + switch (load_cmd.cmd) + { + case llvm::MachO::LoadCommandSegment32: + { + segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); + // We are putting 4 uint32_t values 4 uint64_t values so + // we have to use multiple 32 bit gets below. + segment.vmaddr = data.GetU32 (&offset); + segment.vmsize = data.GetU32 (&offset); + segment.fileoff = data.GetU32 (&offset); + segment.filesize = data.GetU32 (&offset); + // Extract maxprot, initprot, nsects and flags all at once + data.GetU32(&offset, &segment.maxprot, 4); + dylib_info.segments.push_back (segment); + } + break; + + case llvm::MachO::LoadCommandSegment64: + { + segment.name.SetTrimmedCStringWithLength ((const char *)data.GetData(&offset, 16), 16); + // Extract vmaddr, vmsize, fileoff, and filesize all at once + data.GetU64(&offset, &segment.vmaddr, 4); + // Extract maxprot, initprot, nsects and flags all at once + data.GetU32(&offset, &segment.maxprot, 4); + dylib_info.segments.push_back (segment); + } + break; + + case llvm::MachO::LoadCommandUUID: + dylib_info.uuid.SetBytes(data.GetData (&offset, 16)); + break; + + default: + break; + } + // Set offset to be the beginning of the next load command. + offset = load_cmd_offset + load_cmd.cmdsize; + } + } +#if 0 + // No slide in the kernel... + + // All sections listed in the dyld image info structure will all + // either be fixed up already, or they will all be off by a single + // slide amount that is determined by finding the first segment + // that is at file offset zero which also has bytes (a file size + // that is greater than zero) in the object file. + + // Determine the slide amount (if any) + const size_t num_sections = dylib_info.segments.size(); + for (size_t i = 0; i < num_sections; ++i) + { + // Iterate through the object file sections to find the + // first section that starts of file offset zero and that + // has bytes in the file... + if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0) + { + dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr; + // We have found the slide amount, so we can exit + // this for loop. + break; + } + } +#endif + return cmd_idx; +} + +//---------------------------------------------------------------------- +// Dump a Segment to the file handle provided. +//---------------------------------------------------------------------- +void +DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, lldb::addr_t slide) const +{ + if (log) + { + if (slide == 0) + log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx)", + name.AsCString(""), + vmaddr + slide, + vmaddr + slide + vmsize); + else + log->Printf ("\t\t%16s [0x%16.16llx - 0x%16.16llx) slide = 0x%llx", + name.AsCString(""), + vmaddr + slide, + vmaddr + slide + vmsize, + slide); + } +} + +const DynamicLoaderMacOSXKernel::Segment * +DynamicLoaderMacOSXKernel::OSKextLoadedKextSummary::FindSegment (const ConstString &name) const +{ + const size_t num_segments = segments.size(); + for (size_t i=0; i segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) + + if (address == LLDB_INVALID_ADDRESS) + { + if (u) + { + log->Printf("\t uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name='%s' (UNLOADED)", + u[ 0], u[ 1], u[ 2], u[ 3], + u[ 4], u[ 5], u[ 6], u[ 7], + u[ 8], u[ 9], u[10], u[11], + u[12], u[13], u[14], u[15], + name); + } + else + log->Printf("\t name='%s' (UNLOADED)", name); + } + else + { + if (u) + { + log->Printf("\taddress=0x%16.16llx uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X name='%s'", + address, + u[ 0], u[ 1], u[ 2], u[ 3], + u[ 4], u[ 5], u[ 6], u[ 7], + u[ 8], u[ 9], u[10], u[11], + u[12], u[13], u[14], u[15], + name); + } + else + { + log->Printf("\taddress=0x%16.16llx path='%s/%s'", address, name); + } + for (uint32_t i=0; iPrintf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }", + m_kext_summary_header_addr, + m_kext_summary_header.version, + m_kext_summary_header.entry_size, + m_kext_summary_header.entry_count, + m_kext_summary_header.reserved); + + size_t i; + const size_t count = m_kext_summaries.size(); + if (count > 0) + { + log->PutCString("Loaded:"); + for (i = 0; iGetState())); + Clear(true); + m_process = process; + m_process->GetTarget().GetSectionLoadList().Clear(); +} + +bool +DynamicLoaderMacOSXKernel::SetNotificationBreakpoint () +{ + // TODO: Add breakpoint to detected dynamic kext loads/unloads. We aren't + // doing any live dynamic checks for kernel kexts being loaded or unloaded + // on the fly yet. +// DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); +// if (m_break_id == LLDB_INVALID_BREAK_ID) +// { +// if (m_kext_summaries.notification != LLDB_INVALID_ADDRESS) +// { +// Address so_addr; +// // Set the notification breakpoint and install a breakpoint +// // callback function that will get called each time the +// // breakpoint gets hit. We will use this to track when shared +// // libraries get loaded/unloaded. +// +// if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_kext_summaries.notification, so_addr)) +// { +// Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get(); +// dyld_break->SetCallback (DynamicLoaderMacOSXKernel::NotifyBreakpointHit, this, true); +// m_break_id = dyld_break->GetID(); +// } +// } +// } + return m_break_id != LLDB_INVALID_BREAK_ID; +} + +//---------------------------------------------------------------------- +// Member function that gets called when the process state changes. +//---------------------------------------------------------------------- +void +DynamicLoaderMacOSXKernel::PrivateProcessStateChanged (Process *process, StateType state) +{ + DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s(%s)\n", __FUNCTION__, StateAsCString(state)); + switch (state) + { + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateInvalid: + case eStateUnloaded: + case eStateExited: + case eStateDetached: + Clear(false); + break; + + case eStateStopped: + // Keep trying find dyld and set our notification breakpoint each time + // we stop until we succeed + if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) + { + if (LoadKernelModule()) + { + } + + SetNotificationBreakpoint (); + } + break; + + case eStateRunning: + case eStateStepping: + case eStateCrashed: + case eStateSuspended: + break; + + default: + break; + } +} + +ThreadPlanSP +DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) +{ + ThreadPlanSP thread_plan_sp; + StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); + const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); + Symbol *current_symbol = current_context.symbol; + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + + if (current_symbol != NULL) + { + if (current_symbol->IsTrampoline()) + { + const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled); + + if (trampoline_name) + { + SymbolContextList target_symbols; + ModuleList &images = thread.GetProcess().GetTarget().GetImages(); + images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols); + // FIXME - Make the Run to Address take multiple addresses, and + // run to any of them. + uint32_t num_symbols = target_symbols.GetSize(); + if (num_symbols == 1) + { + SymbolContext context; + AddressRange addr_range; + if (target_symbols.GetContextAtIndex(0, context)) + { + context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); + thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others)); + } + else + { + if (log) + log->Printf ("Couldn't resolve the symbol context."); + } + } + else if (num_symbols > 1) + { + std::vector addresses; + addresses.resize (num_symbols); + for (uint32_t i = 0; i < num_symbols; i++) + { + SymbolContext context; + AddressRange addr_range; + if (target_symbols.GetContextAtIndex(i, context)) + { + context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); + lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget()); + addresses[i] = load_addr; + } + } + if (addresses.size() > 0) + thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others)); + else + { + if (log) + log->Printf ("Couldn't resolve the symbol contexts."); + } + } + else + { + if (log) + { + log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); + } + } + } + } + } + else + { + if (log) + log->Printf ("Could not find symbol for step through."); + } + + return thread_plan_sp; +} + +Error +DynamicLoaderMacOSXKernel::CanLoadImage () +{ + Error error; + error.SetErrorString("always unsafe to load or unload shared libraries in the darwin kernel"); + return error; +} + +void +DynamicLoaderMacOSXKernel::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + GetPluginDescriptionStatic(), + CreateInstance); +} + +void +DynamicLoaderMacOSXKernel::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + + +const char * +DynamicLoaderMacOSXKernel::GetPluginNameStatic() +{ + return "dynamic-loader.macosx-kernel"; +} + +const char * +DynamicLoaderMacOSXKernel::GetPluginDescriptionStatic() +{ + return "Dynamic loader plug-in that watches for shared library loads/unloads in the MacOSX kernel."; +} + + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ +const char * +DynamicLoaderMacOSXKernel::GetPluginName() +{ + return "DynamicLoaderMacOSXKernel"; +} + +const char * +DynamicLoaderMacOSXKernel::GetShortPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +DynamicLoaderMacOSXKernel::GetPluginVersion() +{ + return 1; +} + Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h?rev=134672&view=auto ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h (added) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Thu Jul 7 19:48:09 2011 @@ -0,0 +1,418 @@ +//===-- DynamicLoaderMacOSXKernel.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DynamicLoaderMacOSXKernel_h_ +#define liblldb_DynamicLoaderMacOSXKernel_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +#include "llvm/Support/MachO.h" + +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/TimeValue.h" +#include "lldb/Core/UUID.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/Process.h" + +class DynamicLoaderMacOSXKernel : public lldb_private::DynamicLoader +{ +public: + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void + Initialize(); + + static void + Terminate(); + + static const char * + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + static lldb_private::DynamicLoader * + CreateInstance (lldb_private::Process *process, bool force); + + DynamicLoaderMacOSXKernel (lldb_private::Process *process); + + virtual + ~DynamicLoaderMacOSXKernel (); + //------------------------------------------------------------------ + /// Called after attaching a process. + /// + /// Allow DynamicLoader plug-ins to execute some code after + /// attaching to a process. + //------------------------------------------------------------------ + virtual void + DidAttach (); + + virtual void + DidLaunch (); + + virtual lldb::ThreadPlanSP + GetStepThroughTrampolinePlan (lldb_private::Thread &thread, + bool stop_others); + + virtual lldb_private::Error + CanLoadImage (); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual const char * + GetPluginName(); + + virtual const char * + GetShortPluginName(); + + virtual uint32_t + GetPluginVersion(); + +protected: + void + PrivateInitialize (lldb_private::Process *process); + + void + PrivateProcessStateChanged (lldb_private::Process *process, + lldb::StateType state); + bool + LoadKernelModule (); + + bool + DidSetNotificationBreakpoint () const; + + void + Clear (bool clear_process); + + void + PutToLog (lldb_private::Log *log) const; + + static bool + NotifyBreakpointHit (void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + uint32_t + AddrByteSize() + { + switch (m_kernel.header.magic) + { + case llvm::MachO::HeaderMagic32: + case llvm::MachO::HeaderMagic32Swapped: + return 4; + + case llvm::MachO::HeaderMagic64: + case llvm::MachO::HeaderMagic64Swapped: + return 8; + + default: + break; + } + return 0; + } + + static lldb::ByteOrder + GetByteOrderFromMagic (uint32_t magic) + { + switch (magic) + { + case llvm::MachO::HeaderMagic32: + case llvm::MachO::HeaderMagic64: + return lldb::endian::InlHostByteOrder(); + + case llvm::MachO::HeaderMagic32Swapped: + case llvm::MachO::HeaderMagic64Swapped: + if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig) + return lldb::eByteOrderLittle; + else + return lldb::eByteOrderBig; + + default: + break; + } + return lldb::eByteOrderInvalid; + } + + bool + ReadMachHeader (lldb::addr_t addr, + llvm::MachO::mach_header *header, + lldb_private::DataExtractor *load_command_data); + class Segment + { + public: + + Segment() : + name(), + vmaddr(LLDB_INVALID_ADDRESS), + vmsize(0), + fileoff(0), + filesize(0), + maxprot(0), + initprot(0), + nsects(0), + flags(0) + { + } + + lldb_private::ConstString name; + lldb::addr_t vmaddr; + lldb::addr_t vmsize; + lldb::addr_t fileoff; + lldb::addr_t filesize; + uint32_t maxprot; + uint32_t initprot; + uint32_t nsects; + uint32_t flags; + + bool + operator==(const Segment& rhs) const + { + return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; + } + + void + PutToLog (lldb_private::Log *log, + lldb::addr_t slide) const; + + }; + + enum { KERNEL_MODULE_MAX_NAME = 64u }; + + struct OSKextLoadedKextSummary + { + char name[KERNEL_MODULE_MAX_NAME]; + lldb::ModuleSP module_sp; + lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros + uint64_t address; + uint64_t size; + uint64_t version; + uint32_t load_tag; + uint32_t flags; + uint64_t reference_list; + llvm::MachO::mach_header header; // The mach header for this image + std::vector segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) + + OSKextLoadedKextSummary() : + module_sp (), + uuid (), + address (LLDB_INVALID_ADDRESS), + size (0), + version (0), + load_tag (0), + flags (0), + reference_list (0), + header(), + segments() + { + name[0] = '\0'; + } + + void + Clear (bool load_cmd_data_only) + { + if (!load_cmd_data_only) + { + address = LLDB_INVALID_ADDRESS; + size = 0; + version = 0; + load_tag = 0; + flags = 0; + reference_list = 0; + name[0] = '\0'; + ::memset (&header, 0, sizeof(header)); + } + module_sp.reset(); + uuid.Clear(); + segments.clear(); + } + + bool + operator == (const OSKextLoadedKextSummary& rhs) const + { + return address == rhs.address + && size == rhs.size + //&& module_sp.get() == rhs.module_sp.get() + && uuid == rhs.uuid + && version == rhs.version + && load_tag == rhs.load_tag + && flags == rhs.flags + && reference_list == rhs.reference_list + && strncmp (name, rhs.name, KERNEL_MODULE_MAX_NAME) == 0 + && memcmp(&header, &rhs.header, sizeof(header)) == 0 + && segments == rhs.segments; + } + + bool + UUIDValid() const + { + return uuid.IsValid(); + } + + uint32_t + GetAddressByteSize () + { + if (header.cputype) + { + if (header.cputype & llvm::MachO::CPUArchABI64) + return 8; + else + return 4; + } + return 0; + } + + lldb::ByteOrder + GetByteOrder() + { + switch (header.magic) + { + case llvm::MachO::HeaderMagic32: // MH_MAGIC + case llvm::MachO::HeaderMagic64: // MH_MAGIC_64 + return lldb::endian::InlHostByteOrder(); + + case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM + case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64 + if (lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) + return lldb::eByteOrderBig; + else + return lldb::eByteOrderLittle; + default: + assert (!"invalid header.magic value"); + break; + } + return lldb::endian::InlHostByteOrder(); + } + + lldb_private::ArchSpec + GetArchitecture () const + { + return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype); + } + + const Segment * + FindSegment (const lldb_private::ConstString &name) const; + + void + PutToLog (lldb_private::Log *log) const; + + typedef std::vector collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + }; + + struct OSKextLoadedKextSummaryHeader + { + uint32_t version; + uint32_t entry_size; + uint32_t entry_count; + uint32_t reserved; /* explicit alignment for gdb */ + lldb::addr_t image_infos_addr; + + OSKextLoadedKextSummaryHeader() : + version (0), + entry_size (0), + entry_count (0), + reserved (0), + image_infos_addr (LLDB_INVALID_ADDRESS) + { + } + + void + Clear() + { + version = 0; + entry_size = 0; + entry_count = 0; + reserved = 0; + image_infos_addr = LLDB_INVALID_ADDRESS; + } + + bool + IsValid() const + { + return version >= 1 || version <= 2; + } + }; + + void + RegisterNotificationCallbacks(); + + void + UnregisterNotificationCallbacks(); + + uint32_t + ParseLoadCommands (const lldb_private::DataExtractor& data, + OSKextLoadedKextSummary& dylib_info); + + bool + UpdateImageLoadAddress(OSKextLoadedKextSummary& info); + + bool + FindTargetModule (OSKextLoadedKextSummary &image_info, + bool can_create, + bool *did_create_ptr); + + bool + SetNotificationBreakpoint (); + + bool + ReadAllKextSummaries (bool force); + + bool + ReadKextSummaryHeader (); + + bool + ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count); + + bool + AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos); + + bool + RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); + + void + UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos, + uint32_t infos_count, + bool update_executable); + + bool + UpdateCommPageLoadAddress (lldb_private::Module *module); + + uint32_t + ReadKextSummaries (lldb::addr_t image_infos_addr, + uint32_t image_infos_count, + OSKextLoadedKextSummary::collection &image_infos); + + bool + UnloadImageLoadAddress (OSKextLoadedKextSummary& info); + + OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used + lldb::addr_t m_kext_summary_header_addr; + OSKextLoadedKextSummaryHeader m_kext_summary_header; + uint32_t m_kext_summary_header_stop_id; // The process stop ID that "m_kext_summary_header" is valid for + lldb::user_id_t m_break_id; + OSKextLoadedKextSummary::collection m_kext_summaries; + uint32_t m_kext_summaries_stop_id; // The process stop ID that "m_kext_summaries" is valid for + mutable lldb_private::Mutex m_mutex; + lldb_private::Process::Notifications m_notification_callbacks; + +private: + DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXKernel); +}; + +#endif // liblldb_DynamicLoaderMacOSXKernel_h_ Added: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile?rev=134672&view=auto ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile (added) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/Makefile Thu Jul 7 19:48:09 2011 @@ -0,0 +1,14 @@ +##===- source/Plugins/Disassembler/llvm/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLDB_LEVEL := ../../../.. +LIBRARYNAME := lldbPluginDynamicLoaderMacOSXKernel +BUILD_ARCHIVE = 1 + +include $(LLDB_LEVEL)/Makefile Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=134672&r1=134671&r2=134672&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Thu Jul 7 19:48:09 2011 @@ -1275,6 +1275,46 @@ result.GetImmediateErrorStream()->Flush(); } +bool +Target::LoadModuleWithSlide (Module *module, lldb::addr_t slide) +{ + bool changed = false; + if (module) + { + ObjectFile *object_file = module->GetObjectFile(); + if (object_file) + { + SectionList *section_list = object_file->GetSectionList (); + if (section_list) + { + // All sections listed in the dyld image info structure will all + // either be fixed up already, or they will all be off by a single + // slide amount that is determined by finding the first segment + // that is at file offset zero which also has bytes (a file size + // that is greater than zero) in the object file. + + // Determine the slide amount (if any) + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) + { + // Iterate through the object file sections to find the + // first section that starts of file offset zero and that + // has bytes in the file... + Section *section = section_list->GetSectionAtIndex (sect_idx).get(); + if (section) + { + if (m_section_load_list.SetSectionLoadAddress (section, section->GetFileAddress() + slide)) + changed = true; + } + } + } + } + } + return changed; +} + + //-------------------------------------------------------------- // class Target::StopHook //-------------------------------------------------------------- From johnny.chen at apple.com Thu Jul 7 20:01:45 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 08 Jul 2011 01:01:45 -0000 Subject: [Lldb-commits] [lldb] r134673 - /lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py Message-ID: <20110708010145.DF5912A6C12C@llvm.org> Author: johnny Date: Thu Jul 7 20:01:45 2011 New Revision: 134673 URL: http://llvm.org/viewvc/llvm-project?rev=134673&view=rev Log: Rearranged the debug output to come before the assert for function name 'outer_inline'. Right now clang-139 fails the test. Modified: lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py Modified: lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py?rev=134673&r1=134672&r2=134673&view=diff ============================================================================== --- lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py (original) +++ lldb/trunk/test/python_api/frame/inlines/TestInlinedFrame.py Thu Jul 7 20:01:45 2011 @@ -47,16 +47,16 @@ self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) - # The first breakpoint should correspond to an inlined call frame. - frame0 = process.GetThreadAtIndex(0).GetFrameAtIndex(0) - self.assertTrue(frame0.IsInlined() and - frame0.GetFunctionName() == 'outer_inline') - self.runCmd("bt") if self.TraceOn(): print "Full stack traces when first stopped on the breakpoint 'outer_inline':" import lldbutil - print lldbutil.print_stacktraces(process) + print lldbutil.print_stacktraces(process, string_buffer=True) + + # The first breakpoint should correspond to an inlined call frame. + frame0 = process.GetThreadAtIndex(0).GetFrameAtIndex(0) + self.assertTrue(frame0.IsInlined() and + frame0.GetFunctionName() == 'outer_inline') if __name__ == '__main__': From granata.enrico at gmail.com Thu Jul 7 21:51:02 2011 From: granata.enrico at gmail.com (Enrico Granata) Date: Fri, 08 Jul 2011 02:51:02 -0000 Subject: [Lldb-commits] [lldb] r134679 - in /lldb/trunk: include/lldb/Core/ValueObject.h include/lldb/Interpreter/CommandObject.h lldb.xcodeproj/project.pbxproj source/Core/Debugger.cpp source/Core/ValueObject.cpp source/Interpreter/CommandObject.cpp test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py test/functionalities/data-formatter/data-formatter-advanced/main.cpp test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py www/varformats.html Message-ID: <20110708025102.361872A6C12C@llvm.org> Author: enrico Date: Thu Jul 7 21:51:01 2011 New Revision: 134679 URL: http://llvm.org/viewvc/llvm-project?rev=134679&view=rev Log: final fix for the global constructors issue new GetValueForExpressionPath() method in ValueObject to navigate expression paths in a more bitfield vs slices aware way changes to the varformats.html document (WIP) Modified: lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Interpreter/CommandObject.h lldb/trunk/lldb.xcodeproj/project.pbxproj lldb/trunk/source/Core/Debugger.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Interpreter/CommandObject.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py lldb/trunk/www/varformats.html Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Thu Jul 7 21:51:01 2011 @@ -73,10 +73,111 @@ enum ValueObjectRepresentationStyle { - eDisplayValue, + eDisplayValue = 1, eDisplaySummary, eDisplayLanguageSpecific }; + + enum ExpressionPathScanEndReason + { + eEndOfString = 1, // out of data to parse + eNoSuchChild, // child element not found + eEmptyRangeNotAllowed, // [] only allowed for arrays + eDotInsteadOfArrow, // . used when -> should be used + eArrowInsteadOfDot, // -> used when . should be used + eFragileIVarNotAllowed, // ObjC ivar expansion not allowed + eRangeOperatorNotAllowed, // [] not allowed by options + eRangeOperatorInvalid, // [] not valid on objects other than scalars, pointers or arrays + eArrayRangeOperatorMet, // [] is good for arrays, but I cannot parse it + eBitfieldRangeOperatorMet, // [] is good for bitfields, but I cannot parse after it + eUnexpectedSymbol, // something is malformed in the expression + eTakingAddressFailed, // impossible to apply & operator + eDereferencingFailed, // impossible to apply * operator + eUnknown = 0xFFFF + }; + + enum ExpressionPathEndResultType + { + ePlain = 1, // anything but... + eBitfield, // a bitfield + eBoundedRange, // a range [low-high] + eUnboundedRange, // a range [] + eInvalid = 0xFFFF + }; + + enum ExpressionPathAftermath + { + eNothing = 1, // just return it + eDereference, // dereference the target + eTakeAddress // take target's address + }; + + struct GetValueForExpressionPathOptions + { + bool m_check_dot_vs_arrow_syntax; + bool m_no_fragile_ivar; + bool m_allow_bitfields_syntax; + + GetValueForExpressionPathOptions(bool dot = false, + bool no_ivar = false, + bool bitfield = true) : + m_check_dot_vs_arrow_syntax(dot), + m_no_fragile_ivar(no_ivar), + m_allow_bitfields_syntax(bitfield) + { + } + + GetValueForExpressionPathOptions& + DoCheckDotVsArrowSyntax() + { + m_check_dot_vs_arrow_syntax = true; + return *this; + } + + GetValueForExpressionPathOptions& + DontCheckDotVsArrowSyntax() + { + m_check_dot_vs_arrow_syntax = false; + return *this; + } + + GetValueForExpressionPathOptions& + DoAllowFragileIVar() + { + m_no_fragile_ivar = false; + return *this; + } + + GetValueForExpressionPathOptions& + DontAllowFragileIVar() + { + m_no_fragile_ivar = true; + return *this; + } + + GetValueForExpressionPathOptions& + DoAllowBitfieldSyntax() + { + m_allow_bitfields_syntax = true; + return *this; + } + + GetValueForExpressionPathOptions& + DontAllowBitfieldSyntax() + { + m_allow_bitfields_syntax = false; + return *this; + } + + static const GetValueForExpressionPathOptions + DefaultOptions() + { + static GetValueForExpressionPathOptions g_default_options; + + return g_default_options; + } + + }; class EvaluationPoint { @@ -280,6 +381,14 @@ virtual void GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat = eDereferencePointers); + lldb::ValueObjectSP + GetValueForExpressionPath(const char* expression, + const char** first_unparsed = NULL, + ExpressionPathScanEndReason* reason_to_stop = NULL, + ExpressionPathEndResultType* final_value_type = NULL, + const GetValueForExpressionPathOptions& options = GetValueForExpressionPathOptions::DefaultOptions(), + ExpressionPathAftermath* final_task_on_target = NULL); + virtual bool IsInScope () { @@ -636,6 +745,15 @@ //------------------------------------------------------------------ // For ValueObject only //------------------------------------------------------------------ + + lldb::ValueObjectSP + GetValueForExpressionPath_Impl(const char* expression, + const char** first_unparsed, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_value_type, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* final_task_on_target); + DISALLOW_COPY_AND_ASSIGN (ValueObject); }; Modified: lldb/trunk/include/lldb/Interpreter/CommandObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/CommandObject.h?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/include/lldb/Interpreter/CommandObject.h (original) +++ lldb/trunk/include/lldb/Interpreter/CommandObject.h Thu Jul 7 21:51:01 2011 @@ -33,6 +33,18 @@ { ArgumentHelpCallbackFunction *help_callback; bool self_formatting; + + const char* + operator () () const + { + return (*help_callback)(); + } + + operator bool() const + { + return (help_callback != NULL); + } + }; struct ArgumentTableEntry // Entries in the main argument information table Modified: lldb/trunk/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lldb.xcodeproj/project.pbxproj?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj (original) +++ lldb/trunk/lldb.xcodeproj/project.pbxproj Thu Jul 7 21:51:01 2011 @@ -1786,12 +1786,12 @@ 26F996A7119B79C300412154 /* ARM_DWARF_Registers.h */, 26ECA04213665FED008D1F18 /* ARM_DWARF_Registers.cpp */, 26F996A8119B79C300412154 /* ARM_GCC_Registers.h */, - 2660D9F611922A1300958FBD /* StringExtractor.cpp */, 2660D9F711922A1300958FBD /* StringExtractor.h */, - 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */, + 2660D9F611922A1300958FBD /* StringExtractor.cpp */, 2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */, - 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */, + 2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */, 2682F16B115EDA0D00CCFF99 /* PseudoTerminal.h */, + 2682F16A115EDA0D00CCFF99 /* PseudoTerminal.cpp */, ); name = Utility; sourceTree = ""; Modified: lldb/trunk/source/Core/Debugger.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/source/Core/Debugger.cpp (original) +++ lldb/trunk/source/Core/Debugger.cpp Thu Jul 7 21:51:01 2011 @@ -694,7 +694,7 @@ } } -// #define VERBOSE_FORMATPROMPT_OUTPUT +//#define VERBOSE_FORMATPROMPT_OUTPUT #ifdef VERBOSE_FORMATPROMPT_OUTPUT #define IFERROR_PRINT_IT if (error.Fail()) \ { \ @@ -832,35 +832,41 @@ ExpandIndexedExpression(ValueObject* vobj, uint32_t index, StackFrame* frame, - Error error) + bool deref_pointer) { - ValueObjectSP item; - bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType()); - - if (is_array) - return vobj->GetChildAtIndex(index, true); - else - { - const char* ptr_deref_format = "%s[%d]"; - char* ptr_deref_buffer = new char[1024]; - StreamString expr_path_string; - vobj->GetExpressionPath(expr_path_string, true, ValueObject::eHonorPointers); - const char* expr_path = expr_path_string.GetData(); + const char* ptr_deref_format = "[%d]"; + std::auto_ptr ptr_deref_buffer(new char[10]); + ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index); #ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to deref in phase 0: %s\n",expr_path); + printf("name to deref: %s\n",ptr_deref_buffer.get()); #endif //VERBOSE_FORMATPROMPT_OUTPUT - ::sprintf(ptr_deref_buffer, ptr_deref_format, expr_path, index); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to deref in phase 1: %s\n",ptr_deref_buffer); + const char* first_unparsed; + ValueObject::GetValueForExpressionPathOptions options; + ValueObject::ExpressionPathEndResultType final_value_type; + ValueObject::ExpressionPathScanEndReason reason_to_stop; + ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eDereference : ValueObject::eNothing); + ValueObjectSP item = vobj->GetValueForExpressionPath (ptr_deref_buffer.get(), + &first_unparsed, + &reason_to_stop, + &final_value_type, + options, + &what_next); + if (!item) + { +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("ERROR: unparsed portion = %s, why stopping = %d," + " final_value_type %d\n", + first_unparsed, reason_to_stop, final_value_type); #endif //VERBOSE_FORMATPROMPT_OUTPUT - lldb::VariableSP var_sp; - item = frame->GetValueForVariableExpressionPath (ptr_deref_buffer, - eNoDynamicValues, - 0, - var_sp, - error); - delete ptr_deref_buffer; } +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + else + { + printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," + " final_value_type %d\n", + first_unparsed, reason_to_stop, final_value_type); + } +#endif //VERBOSE_FORMATPROMPT_OUTPUT return item; } @@ -954,8 +960,9 @@ const RegisterInfo *reg_info = NULL; RegisterContext *reg_ctx = NULL; bool do_deref_pointer = false; - bool did_deref_pointer = true; - + ValueObject::ExpressionPathScanEndReason reason_to_stop; + ValueObject::ExpressionPathEndResultType final_value_type; + // Each variable must set success to true below... bool var_success = false; switch (var_name_begin[0]) @@ -971,6 +978,10 @@ case 'v': { + ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? + ValueObject::eDereference : ValueObject::eNothing); + ValueObject::GetValueForExpressionPathOptions options; + options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar(); ValueObject::ValueObjectRepresentationStyle val_obj_display = ValueObject::eDisplaySummary; ValueObject* target = NULL; lldb::Format custom_format = eFormatInvalid; @@ -980,6 +991,8 @@ int64_t index_lower = -1; int64_t index_higher = -1; bool is_array_range = false; + const char* first_unparsed; + if (!vobj) break; // simplest case ${var}, just print vobj's value if (::strncmp (var_name_begin, "var}", strlen("var}")) == 0) @@ -1025,57 +1038,47 @@ &index_higher); Error error; - target = ExpandExpressionPath (vobj, - exe_ctx->frame, - &do_deref_pointer, - var_name_begin, - var_name_final, - error).get(); - - if (error.Fail() || !target) + + std::auto_ptr expr_path(new char[var_name_final-var_name_begin-1]); + ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1); + memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3); + +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("symbol to expand: %s\n",expr_path.get()); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + + target = vobj->GetValueForExpressionPath(expr_path.get(), + &first_unparsed, + &reason_to_stop, + &final_value_type, + options, + &what_next).get(); + + if (!target) { #ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("ERROR: %s\n",error.AsCString("unknown")); + printf("ERROR: unparsed portion = %s, why stopping = %d," + " final_value_type %d\n", + first_unparsed, reason_to_stop, final_value_type); #endif //VERBOSE_FORMATPROMPT_OUTPUT - if (var_name_final_if_array_range) - { - target = ExpandExpressionPath(vobj, - exe_ctx->frame, - &do_deref_pointer, - var_name_begin, - var_name_final_if_array_range, - error).get(); - } - - if (var_name_final_if_array_range && (error.Fail() || !target)) - { - bool fake_do_deref = false; - target = ExpandExpressionPath(vobj, - exe_ctx->frame, - &fake_do_deref, - var_name_begin, - var_name_final_if_array_range, - error).get(); - - did_deref_pointer = false; - - if (target && ClangASTContext::IsArrayType(target->GetClangType())) - error.Clear(); - else - error.SetErrorString("error in expression"); - } - - IFERROR_PRINT_IT - else - is_array_range = true; + break; } - - if (did_deref_pointer) - do_deref_pointer = false; // I have honored the request to deref - +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + else + { + printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," + " final_value_type %d\n", + first_unparsed, reason_to_stop, final_value_type); + } +#endif //VERBOSE_FORMATPROMPT_OUTPUT } else break; + + is_array_range = (final_value_type == ValueObject::eBoundedRange || + final_value_type == ValueObject::eUnboundedRange); + + do_deref_pointer = (what_next == ValueObject::eDereference); if (do_deref_pointer && !is_array_range) { @@ -1092,30 +1095,22 @@ var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); else { - bool is_array = ClangASTContext::IsArrayType(vobj->GetClangType()); - bool is_pointer = ClangASTContext::IsPointerType(vobj->GetClangType()); + bool is_array = ClangASTContext::IsArrayType(target->GetClangType()); + bool is_pointer = ClangASTContext::IsPointerType(target->GetClangType()); if (!is_array && !is_pointer) break; - char* special_directions = NULL; + const char* special_directions = NULL; + StreamString special_directions_writer; if (close_bracket_position && (var_name_end-close_bracket_position > 1)) { - int base_len = var_name_end-close_bracket_position; - special_directions = new char[7+base_len]; - int star_offset = (do_deref_pointer ? 1 : 0); - special_directions[0] = '$'; - special_directions[1] = '{'; - if (do_deref_pointer) - special_directions[2] = '*'; - special_directions[2+star_offset] = 'v'; - special_directions[3+star_offset] = 'a'; - special_directions[4+star_offset] = 'r'; - memcpy(special_directions+5+star_offset, close_bracket_position+1, base_len); - special_directions[base_len+5+star_offset] = '\0'; -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("%s\n",special_directions); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + ConstString additional_data; + additional_data.SetCStringWithLength(close_bracket_position+1, var_name_end-close_bracket_position-1); + special_directions_writer.Printf("${%svar%s}", + do_deref_pointer ? "*" : "", + additional_data.GetCString()); + special_directions = special_directions_writer.GetData(); } // let us display items index_lower thru index_higher of this array @@ -1127,13 +1122,24 @@ for (;index_lower<=index_higher;index_lower++) { - Error error; - ValueObject* item = ExpandIndexedExpression(vobj, + ValueObject* item = ExpandIndexedExpression(target, index_lower, exe_ctx->frame, - error).get(); + false).get(); - IFERROR_PRINT_IT + if (!item) + { +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + printf("ERROR\n"); +#endif //VERBOSE_FORMATPROMPT_OUTPUT + } +#ifdef VERBOSE_FORMATPROMPT_OUTPUT + else + { + printf("special_directions: %s\n",special_directions); + } +#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (!special_directions) var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); else Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Thu Jul 7 21:51:01 2011 @@ -1366,6 +1366,412 @@ } } +lldb::ValueObjectSP +ValueObject::GetValueForExpressionPath(const char* expression, + const char** first_unparsed, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_value_type, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* final_task_on_target) +{ + + const char* dummy_first_unparsed; + ExpressionPathScanEndReason dummy_reason_to_stop; + ExpressionPathEndResultType dummy_final_value_type; + ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eNothing; + + ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, + first_unparsed ? first_unparsed : &dummy_first_unparsed, + reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, + final_value_type ? final_value_type : &dummy_final_value_type, + options, + final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); + + if (!final_task_on_target || *final_task_on_target == ValueObject::eNothing) + { + return ret_val; + } + if (ret_val.get() && *final_value_type == ePlain) // I can only deref and takeaddress of plain objects + { + if (*final_task_on_target == ValueObject::eDereference) + { + Error error; + ValueObjectSP final_value = ret_val->Dereference(error); + if (error.Fail() || !final_value.get()) + { + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_value_type = ValueObject::eInvalid; + return ValueObjectSP(); + } + else + { + *final_task_on_target = ValueObject::eNothing; + return final_value; + } + } + if (*final_task_on_target == ValueObject::eTakeAddress) + { + Error error; + ValueObjectSP final_value = ret_val->AddressOf(error); + if (error.Fail() || !final_value.get()) + { + *reason_to_stop = ValueObject::eTakingAddressFailed; + *final_value_type = ValueObject::eInvalid; + return ValueObjectSP(); + } + else + { + *final_task_on_target = ValueObject::eNothing; + return final_value; + } + } + } + return ret_val; // final_task_on_target will still have its original value, so you know I did not do it +} + +lldb::ValueObjectSP +ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, + const char** first_unparsed, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_result, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* what_next) +{ + ValueObjectSP root = GetSP(); + + if (!root.get()) + return ValueObjectSP(); + + *first_unparsed = expression_cstr; + + while (true) + { + + const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr + + lldb::clang_type_t root_clang_type = root->GetClangType(); + + if (!expression_cstr || *expression_cstr == '\0') + { + *reason_to_stop = ValueObject::eEndOfString; + return root; + } + + switch (*expression_cstr) + { + case '-': + { + if (options.m_check_dot_vs_arrow_syntax && + !ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use -> on a non-pointer and I must catch the error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eArrowInsteadOfDot; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + const uint32_t pointer_type_flags = ClangASTContext::GetTypeInfo (root_clang_type, NULL, NULL); + if ((pointer_type_flags & ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden + (pointer_type_flags & ClangASTContext::eTypeIsPointer) && + options.m_no_fragile_ivar) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eFragileIVarNotAllowed; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + if (expression_cstr[1] != '>') + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + expression_cstr++; // skip the - + } + case '.': // or fallthrough from -> + { + if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' && + ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use . on a pointer and I must catch the error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eDotInsteadOfArrow; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + expression_cstr++; // skip . + const char *next_separator = strpbrk(expression_cstr+1,"-.["); + ConstString child_name; + if (!next_separator) // if no other separator just expand this last layer + { + child_name.SetCString (expression_cstr); + root = root->GetChildMemberWithName(child_name, true); + if (root.get()) // we know we are done, so just return + { + *first_unparsed = '\0'; + *reason_to_stop = ValueObject::eEndOfString; + *final_result = ValueObject::ePlain; + return root; + } + else + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + } + else // other layers do expand + { + child_name.SetCStringWithLength(expression_cstr, next_separator - expression_cstr); + root = root->GetChildMemberWithName(child_name, true); + if (root.get()) // store the new root and move on + { + *first_unparsed = next_separator; + *final_result = ValueObject::ePlain; + continue; + } + else + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + } + break; + } + case '[': + { + if (!ClangASTContext::IsArrayType(root_clang_type) && !ClangASTContext::IsPointerType(root_clang_type)) // if this is not a T[] nor a T* + { + if (!ClangASTContext::IsScalarType(root_clang_type)) // if this is not even a scalar, this syntax is just plain wrong! + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eRangeOperatorInvalid; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eRangeOperatorNotAllowed; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + } + if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays + { + if (!ClangASTContext::IsArrayType(root_clang_type)) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else // even if something follows, we cannot expand unbounded ranges, just let the caller do it + { + *first_unparsed = expression_cstr+2; + *reason_to_stop = ValueObject::eArrayRangeOperatorMet; + *final_result = ValueObject::eUnboundedRange; + return root; + } + } + const char *separator_position = ::strchr(expression_cstr+1,'-'); + const char *close_bracket_position = ::strchr(expression_cstr+1,']'); + if (!close_bracket_position) // if there is no ], this is a syntax error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N] + { + char *end = NULL; + unsigned long index = ::strtoul (expression_cstr+1, &end, 0); + if (!end || end != close_bracket_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays + { + if (ClangASTContext::IsArrayType(root_clang_type)) + { + *first_unparsed = expression_cstr+2; + *reason_to_stop = ValueObject::eArrayRangeOperatorMet; + *final_result = ValueObject::eUnboundedRange; + return root; + } + else + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + } + // from here on we do have a valid index + if (ClangASTContext::IsArrayType(root_clang_type)) + { + root = root->GetChildAtIndex(index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else + { + *first_unparsed = end+1; // skip ] + *final_result = ValueObject::ePlain; + continue; + } + } + else if (ClangASTContext::IsPointerType(root_clang_type)) + { + if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr())) + { + Error error; + root = root->Dereference(error); + if (error.Fail() || !root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else + { + *what_next = eNothing; + continue; + } + } + else + { + root = root->GetSyntheticArrayMemberFromPointer(index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else + { + *first_unparsed = end+1; // skip ] + *final_result = ValueObject::ePlain; + continue; + } + } + } + else /*if (ClangASTContext::IsScalarType(root_clang_type))*/ + { + root = root->GetSyntheticBitFieldChild(index, index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing + { + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet; + *final_result = ValueObject::eBitfield; + return root; + } + } + } + else // we have a low and a high index + { + char *end = NULL; + unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0); + if (!end || end != separator_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + unsigned long index_higher = ::strtoul (separator_position+1, &end, 0); + if (!end || end != close_bracket_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + if (index_lower > index_higher) // swap indices if required + { + unsigned long temp = index_lower; + index_lower = index_higher; + index_higher = temp; + } + if (ClangASTContext::IsScalarType(root_clang_type)) // expansion only works for scalars + { + root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else + { + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eBitfieldRangeOperatorMet; + *final_result = ValueObject::eBitfield; + return root; + } + } + else if (ClangASTContext::IsPointerType(root_clang_type) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + *what_next == ValueObject::eDereference && + ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr())) + { + Error error; + root = root->Dereference(error); + if (error.Fail() || !root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + } + else + { + *what_next = ValueObject::eNothing; + continue; + } + } + else + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eArrayRangeOperatorMet; + *final_result = ValueObject::eBoundedRange; + return root; + } + } + break; + } + default: // some non-separator is in the way + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return ValueObjectSP(); + break; + } + } + } +} + void ValueObject::DumpValueObject ( Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Thu Jul 7 21:51:01 2011 @@ -469,9 +469,9 @@ StreamString name_str; name_str.Printf ("<%s>", entry->arg_name); - if (entry->help_function.help_callback) + if (entry->help_function) { - const char* help_text = (*entry->help_function.help_callback)(); + const char* help_text = entry->help_function(); if (!entry->help_function.self_formatting) { interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text, Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py Thu Jul 7 21:51:01 2011 @@ -159,6 +159,19 @@ substrs = ['0x', '7']) + self.runCmd("type summary clear") + + self.runCmd("type summary add -f \"${*var[].x[0-3]%hex} is a bitfield on a set of integers\" -x \"SimpleWithPointers \[[0-9]\]\"") + self.runCmd("type summary add -f \"${*var.sp.x[0-2]} are low bits of integer ${*var.sp.x}. If I pretend it is an array I get ${var.sp.x[0-5]}\" Couple") + + self.expect("frame variable couple", + substrs = ['1 are low bits of integer 9.', + 'If I pretend it is an array I get [9,']) + + self.expect("frame variable sparray", + substrs = ['[0x0000000f,0x0000000c,0x00000009]']) + + if __name__ == '__main__': import atexit Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-advanced/main.cpp Thu Jul 7 21:51:01 2011 @@ -41,6 +41,38 @@ IWrapPointers() : int_pointer(new int(4)), float_pointer(new float(1.111)) {} }; +struct Simple +{ + int x; + float y; + char z; + Simple(int X, float Y, char Z) : + x(X), + y(Y), + z(Z) + {} +}; + +struct SimpleWithPointers +{ + int *x; + float *y; + char *z; + SimpleWithPointers(int X, float Y, char Z) : + x(new int (X)), + y(new float (Y)), + z(new char (Z)) + {} +}; + +struct Couple +{ + SimpleWithPointers sp; + Simple* s; + Couple(int X, float Y, char Z) : sp(X,Y,Z), + s(new Simple(X,Y,Z)) {} +}; + int main (int argc, const char * argv[]) { @@ -66,6 +98,13 @@ int* pointer = &cool_array[4].integer; IWrapPointers *wrap_pointer = &wrapper; - + + Couple couple(9,9.99,'X'); + + SimpleWithPointers sparray[] = + {SimpleWithPointers(-1,-2,'3'), + SimpleWithPointers(-4,-5,'6'), + SimpleWithPointers(-7,-8,'9')}; + return 0; // Set break point at this line. } \ No newline at end of file Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py (original) +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py Thu Jul 7 21:51:01 2011 @@ -99,6 +99,12 @@ self.expect("frame variable iAmSomewhere", substrs = ['y=0x']) + + self.runCmd("type summary add -f \"y=${var.y},x=${var.x}\" Point") + + self.expect("frame variable iAmSomewhere", + substrs = ['y=6', + 'x=4']) self.runCmd("type summary add -f \"hello\" Point -e") Modified: lldb/trunk/www/varformats.html URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/www/varformats.html?rev=134679&r1=134678&r2=134679&view=diff ============================================================================== --- lldb/trunk/www/varformats.html (original) +++ lldb/trunk/www/varformats.html Thu Jul 7 21:51:01 2011 @@ -1,576 +1,717 @@ - - - - - -LLDB Homepage - - - -
- The LLDB Debugger -
- -
-
- - -
-
-

Variable display

-
-

LLDB was recently modified to allow users to define the - format of the variables display on a per-type basis.

- -

Usually, when you type frame - variable or run some expression - LLDB will automatically choose the best way - to display your results according to its own - logic:

(SimpleWithPointers [3]) - sparray = {
(SimpleWithPointers) [0] = {
- (int *) x = 0x00000001001000f0
(float *) y = - 0x0000000100100100
(char *) z = - 0x0000000100100110 "3"
- }
- (SimpleWithPointers) [1] = {
(int *) x = - 0x0000000100100120
(float *) y = - 0x0000000100100130
(char *) z = - 0x0000000100100140 "6"
- }
- (SimpleWithPointers) [2] = {
(int *) x = - 0x0000000100100150
(float *) y = - 0x0000000100100160
(char *) z = - 0x0000000100100170 "9"
- }
- }
-

- -

However, there are cases in which your idea of - best is different from LLDB's. Now there are two - new commands that enable you to give hints to the debugger - as to how datatypes should be displayed.

- -

Using them you can obtain a format like this one for - sparray, instead of the default shown above: -

- -

- - (SimpleWithPointers [3]) sparray = {
- [0] = (x=0x00000001001000f0 -> -1, y=0x0000000100100100 -> -2, z="3")
- [1] = (x=0x0000000100100120 -> -4, y=0x0000000100100130 -> -5, z="6")
- [2] = (x=0x0000000100100150 -> -7, y=0x0000000100100160 -> -8, z="9")
-}
-
-

-

Variable formatting can be set using the type commands:

-

type format

-

type summary

-

Each of these commands has four subcommands:

-

add: adds a new entry

-

delete: deletes an existing entry

-

list: provides a listing of all entries

-

clear: deletes all entries

- -
- -
- -
-

type format

-
- -

Type formats enable you to quickly override the default format for displaying primitive types (the usual basic C/C++/ObjC types: int, float, char, ...).

-

LLDB has a list of formatting options available out of which you can pick:

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Format nameAbbreviationDescription
defaultthe default LLDB algorithm is used to pick a format
booleanBshow this as a true/false boolean, using the customary rule that 0 is false and everything else is true
binarybshow this as a sequence of bits
bytesyshow the bytes one after the other
e.g. (int) s.x = 07 00 00 00
bytes with ASCIIYshow the bytes, but try to print them as ASCII characters
e.g. (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._....
charactercshow the bytes printed as ASCII characters
e.g. (int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0
printable characterCshow the bytes printed as printable ASCII characters
e.g. (int *) c.sp.x = P.._....
complex floatFinterpret this value as the real and imaginary part of a complex floating-point number
e.g. (int *) c.sp.x = 2.76658e+19 + 4.59163e-41i
c-stringsshow this as a 0-terminated C string
signed decimalishow this as a signed integer number (this does not perform a cast, it simply shows the bytes as signed integer)
enumerationEshow this as an enumeration, printing the value's name if available or the integer value otherwise
e.g. (enum enumType) val_type = eValue2
hexxshow this as in hexadecimal notation (this does not perform a cast, it simply shows the bytes as hex)
floatfshow this as a floating-point number (this does not perform a cast, it simply interprets the bytes as an IEEE754 floating-point value)
octaloshow this in octal notation
OSTypeOshow this as a MacOS OSType
e.g. (float) *c.sp.y = '\n\x1f\xd7\n'
unicode16Ushow this as UTF-16 characters
e.g. (float) *c.sp.y = 0xd70a 0x411f
unicode32show this as UTF-32 characters
e.g. (float) *c.sp.y = 0x411fd70a
unsigned decimalushow this as an unsigned integer number (this does not perform a cast, it simply shows the bytes as unsigned integer)
pointerpshow this as a native pointer (unless this is really a pointer, the resulting address will probably be invalid)
char[]show this as an array of characters
e.g. (char) *c.sp.z = {X}
int8_t[], uint8_t[]
int16_t[], uint16_t[]
int32_t[], uint32_t[]
int64_t[], uint64_t[]
uint128_t[]
show this as an array of the corresponding integer type
e.g.
(int) sarray[0].x = {1 0 0 0}
(int) sarray[0].x = {0x00000001}
float32[], float64[]show this as an array of the corresponding floating-point type
e.g. (int *) pointer = {1.46991e-39 1.4013e-45}
complex integerIinterpret this value as the real and imaginary part of a complex integer number
e.g. (int *) pointer = 1048960 + 1i
character arrayashow this as a character array
e.g. (int *) pointer = \x80\x01\x10\0\x01\0\0\0
- -

Some of the examples shown are willingfully - unnatural ways to print some values, and meant to - show that there is no casting or data-loss occurring - when you change the format of a type. All that lldb - does when you ask it to change format is reinterpret - the bytes for display, leaving the original value - unaltered.

- -

There are two ways to modify the format, one is - temporary and per-variable, the other is permanent - and per-type.

In the first case you can simply - use the -f option to frame - variable, passing it one of the format - names or abbreviations in the previous table:

-

frame variable counter -f hex

-

This has the effect of displaying the value of - counter as an hexadecimal number, and - will keep showing it this way until you either pick a - different format or a subsequent stoppoint is - hit.

Obviously, if you have two - int variables, and you format one as - hex, the other will be left untouched. If for some - reason, you want all int variables to - print out as hex, you must add a format to the - int type.

This is done by typing - type format add -f hex int at the LLDB - command line.

The -f option - accepts one of the format names or abbreviations, and - after that you can give out a list of names to which - you want the new format applied.

A frequent - scenario is that your program has a - typedef for a numeric type that you know - represents something that must be printed in a - certain way. Again, you can add a format just to that - typedef by using type format add with - the name alias.

But things can quickly get - hierarchical. Let's say you have a situation like the - following:

typedef int A;
typedef A - B;
typedef B C;
typedef C D;

-

and you want to show all As as hex, - all Cs as pointers and leave the - defaults untouched for other types.

If you - simply type
type format add -f hex - A
type format add -f pointer C

values - of type B will be shown as hex and - values of type D as pointers.

-

This is because by default LLDB cascades - formats through typedef chains. In order to avoid - that you can use the option -C no to - prevent cascading, thus making the two commands - required to achieve your goal:
type - format add -f hex -C no A
type format add -f - pointer -C no C

Two additional options - that you will want to look at are -p and - -r. These two options prevent LLDB from - applying a format for type T to values - of type T* and T& - respectively.

-

- - (lldb) type format add -f float32[] int
- (lldb) fr var pointer *pointer -T
- (int *) pointer = {1.46991e-39 1.4013e-45}
- (int) *pointer = {1.53302e-42}
- (lldb) type format add -f float32[] int -p
- (lldb) fr var pointer *pointer -T
- (int *) pointer = 0x0000000100100180
- (int) *pointer = {1.53302e-42}
-
-

-

As the previous example highlights, you will most - probably want to use -p for your - formats.

If you need to delete a custom format - simply type type format delete followed - by the name of the type to which the format applies. - To delete ALL formats, use type format - clear. To see all the formats defined, type - type format list.

- -
- -

type - summary

- -

Type summaries enable you to add more information - to the default viewing format for a type, or to - completely replace it with your own display option. - Unlike formats which only apply to basic types, - summaries can be used on every type (basic types, - classes (C++ and Objective-C), arrays, ...).

-

The basic idea beneath type summaries is - extracting information from variables and arranging - it in a format that is suitable for display:

- before adding a summary...
(lldb) - fr var -T one
(i_am_cool) one = {
(int) - integer = 3
(float) floating = 3.14159
- (char) character = 'E'
- }
-

after adding a summary...
- (lldb) fr var one
(i_am_cool) one = int - = 3, float = 3.14159, char = 69

- -

Evidently, somehow we managed to tell LLDB to grab - the three member variables of the - i_am_cool datatype, mix their values - with some text, and even ask it to display the - character member using a custom - format.

The way to do this is add a summary - string to the datatype using the type - summary add command.

Its syntax is - similar to type format add, but some - more options are supported that will be described in - the follow-up.

The main option to type - summary add is -f which accepts - as parameter a summary string. After that, you can - type as many type names as you want to associate the - given summary string to them.

- -
- -
- -
-

Summary Strings

-
- -

So what is the format of the summary strings? - Summary strings can contain plain text, control - characters and special symbols that have access to - information about the current object and the overall - program state.

- -

Normal characters are any text that doesn't - contain a '{', - '}', '$', or - '\' character.

- -

Variable names are found in between a - "${" prefix, and end with a - "}" suffix. In other words, a - variable looks like - "${frame.pc}".

- -

Basically, all the variables described in Frame and Thread Formatting - are accepted. Also acceptable are the control - characters and scoping features described in that - page. Additionally, ${var and - ${*var become acceptable symbols in this - scenario.

The simplest thing you can do is - grab a member variable of a class or structure by - typing its expression path. In the previous - example, the expression path for the floating member - is simply .floating, because all you - have to do to get at it given an object of type - i_am_cool is access it straight away. - Thus, to ask the summary string to display - floating you would type - ${var.floating} (${var is a - placeholder token replaced with whatever variable is - being displayed).

If you have code like the - following:
struct A {
int x;
- int y;
- };
- struct B {
A x;
A y;
int z;
- };
-
the expression path for the y - member of the x member of an object of - type B would be .x.y and - you would type ${var.x.y} to display it - in a summary string for type B.

-

As you could be using a summary string for both - displaying objects of type T or - T* (unless -p is used to - prevent this), the expression paths do not - differentiate between . and - ->, and the above expression path - .x.y would be just as good if you were - displaying a B*, or even if the actual - definition of B were: -
- struct B {
- A *x;
- A y;
- int z;
- };
-
-

-

This is unlike the behaviour of frame - variable which, on the contrary, will enforce - the distinction. As hinted above, the rationale for - this choice is that waiving this distinction enables - one to write a summary string once for type - T and use it for both T and - T* instances. As a summary string is - mostly about extracting nested members' information, - a pointer to an object is just as good as the object - itself for the purpose.

- -

Of course, you can have multiple entries in one - summary string. For instance, the command used to - produce the above summary string for i_am_cool was: -
type summary add -f "int = ${var.integer}, - float = ${var.floating}, char = ${var.character%u}" - i_am_cool

As you can see, the last - expression path also contains a %u - symbol which is nowhere to be found in the actual - member variable name. The symbol is reminding of a - printf() format symbol, and in fact it - has a similar effect. If you add a % sign followed by - any one format name or abbreviation from the above - table after an expression path, the resulting object - will be displyed using exactly that format instead of - the LLDB default one. -

-

There are two more special format symbols that you - can use only as part of a summary string: - %V and %@. The first one - tells LLDB to ignore summary strings for the type of - the object referred by the expression path and - instead print the object's value. The second is only - applicable to Objective-C classes, and tells LLDB to - get the object's description from the Objective-C - runtime. By default, if no format is provided, LLDB - will try to get the object's summary, and if empty - the object's value. If neither can be obtained, - nothing will be displayed.

-

As previously said, pointers and values are - treated the same way when getting to their members in - an expression path. However, if your expression path - leads to a pointer, LLDB will not automatically - dereference it. In order to obtain The deferenced - value for a pointer, your expression path must start - with ${*var instead of - ${var. Because there is no need to - dereference pointers along your way, the - dereferencing symbol only applies to the result of - the whole expression path traversing. -
- e.g. - -
- (lldb) fr var -T c
-(Couple) c = {
- (SimpleWithPointers) sp = {
- (int *) x = 0x00000001001000b0
- (float *) y = 0x00000001001000c0
- (char *) z = 0x00000001001000d0 "X"
- }
- (Simple *) s = 0x00000001001000e0
-}
-(lldb) type summary add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = ${*var.s}" Couple
-(lldb) type summary add -c -p Simple
-(lldb) fr var c
-(Couple) c = int = 9, float = 9.99, char = 88, Simple = (x=9, y=9.99, z='X')
-
-

-

Option -c to type summary - add tells LLDB not to look for a summary - string, but instead to just print a listing of all - the object's children on one line, lay out as in the - previous example. The -p flag is used as - a trick to show that aggregate types can be - dereferenced as well as primitive ones. The above - output would be shown even by typing type - summary add -f "int = ${*var.sp.x}, float = - ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = - ${var.s}" Couple if one took away the - -p flag from the summary for type - Simple.

- -
- -
- -
-

More on summary strings

-
- -

What was described above are the main features - that you can use in summary strings. However, there - are three more features to them.

Sometimes, a - basic type's value actually represents several - different values packed together in a bitfield. With - the classical view, there is no way to look at them. - Hexadecimal display can help, but if the bits - actually span byte boundaries, the help is limited. - Binary view would show it all without ambiguity, but - is often too detailed and hard to read for real-life - scenarios. To cope with the issue, LLDB supports - native bitfield formatting in summary strings. If - your expression paths leads to a so-called scalar - type (the usual int, float, char, double, short, - long, long long, double, long double and unsigned - variants), you can ask LLDB to only grab some bits - out of the value and display them in any format you - like. The syntax is similar to that used for arrays, - just you can also give a pair of indices separated by - a -.
- e.g. -
- - (lldb) fr var float_point
-(float) float_point = -3.14159
-(lldb) type summary add -f "Sign: ${var[31]%B} Exponent: ${var[30-23]%x} Mantissa: ${var[0-22]%u}" float
-(lldb) fr var float_point
-(float) float_point = -3.14159 Sign: true Exponent: 0x00000080 Mantissa: 4788184
-
- In this example, LLDB shows the internal - representation of a float variable by - extracting bitfields out of a float object. If you - give a single index, only that one bit will be - extracted. If you give a pair of indices, all the - bits in the range (extremes included) will be - extracted. Ranges can be specified either by giving - the lower index first, or higher index first (as is - often customary in describing packed data-type - formats).

-

The second additional feature allows you to - display array members inside a summary string. For - instance, you may want to display all arrays of a - given type using a more compact notation than the - default, and then just delve into individual array - members that prove interesting to your debugging - task. You can use a similar syntax to the one used - for bitfields to tell LLDB to format arrays in - special ways. -
- e.g. -
- - (lldb) fr var sarray
-(Simple [3]) sarray = {
- [0] = {
- x = 1
- y = 2
- z = '\x03'
- }
- [1] = {
- x = 4
- y = 5
- z = '\x06'
- }
- [2] = {
- x = 7
- y = 8
- z = '\t'
- }
-}
-(lldb) type summary add -f "${var[].x}" "Simple [3]"
-(lldb) fr var sarray
-(Simple [3]) sarray = [1,4,7]
-
- The [] symbol amounts to: if - var is an array and I knows its size, - apply this summary string to every element of the - array. Here, we are asking LLDB to display - .x for every element of the array, and - in fact this is what happens. If you find some of - those integers anomalous, you can then inspect that - one item in greater detail, without the array format - getting in the way: -
- - (lldb) fr var sarray[1]
-(Simple) sarray[1] = {
- x = 4
- y = 5
- z = '\x06'
-}
-
-

-

You can also ask LLDB to only print a subset of - the array range by using the same syntax used to - extract bit for bitfields.

The same logic - works if you are printing a pointer instead of an - array, however in this latter case, [] - cannot be used and you need to give exact range - limits.

The third, and last, additional - feature does not directly apply to the summary - strings themselves, but is an additional option to - the type summary add command: - -x

As you noticed, in order to - associate the custom summary string to the array - types, one must give the array size as part of the - typename. This can long become tiresome when using - arrays of different sizes, Simple [3], - Simple [9], Simple [12], - ...

If you use the -x option, - type names are treated as regular expressions instead - of type names. This would let you rephrase the above - example as: -
- -(lldb) type summary add -f "${var[].x}" -x "Simple \[[0-9]+\]"
-(lldb) fr var sarray
-(Simple [3]) sarray = [1,4,7]
-
- The above scenario works for Simple [3] - as well as for any other array of - Simple objects.

While this - feature is mostly useful for arrays, you could also - use regular expressions to catch other type sets - grouped by name. However, as regular expression - matching is slower than normal name matching, LLDB - will first try to match by name in any way it can, - and only when this fails, will it resort to regular - expression matching. Thus, if your type has a base - class with a cascading summary, this will be - preferred over any regular expression match for your - type itself.

- -
- -

Finding - summaries 101

- -

While the rules for finding an appropriate - format for a type are relatively simple (just go - through typedef hierarchies), summaries follow a - more complicated process in finding the right - summary string for a variable. Namely, what - happens is:

  • If there is a summary for - the type of the variable, use it
  • If this - object is a pointer, and there is a summary for - the pointee type that does not skip pointers, use - it
  • If this object is a reference, and - there is a summary for the pointee type that does - not skip references, use it
  • If this - object is an Objective-C class with a parent - class, look at the parent class (and parent of - parent, ...)
  • If this object is a C++ - class with base classes, look at base classes (and - bases of bases, ...)
  • If this object is a - C++ class with virtual base classes, look at the - virtual base classes (and bases of bases, - ...)
  • If this object's type is a typedef, - go through typedef hierarchy
  • If - everything has failed, repeat the above search, - looking for regular expressions instead of exact - matches
- -

TODOs

-
- -
  • There's no way to do multiple dereferencing, - and you need to be careful what the dereferencing - operation is binding to in complicated scenarios
  • -
  • There is no way to call functions inside summary - strings, not even const ones
  • -
  • type format add does not support the - -x option
  • Object location cannot - be printed in the summary string
-
- -
- -
-
-
- - \ No newline at end of file + + + + + + LLDB Homepage + + +
The LLDB Debugger
+
+
+ +
+
+

Variable display

+
+ +

LLDB was recently modified to allow users to define custom + formatting options for the variables display.

+ +

Usually, when you type frame variable or + run some expression LLDB will + automatically choose a format to display your results on + a per-type basis, as in the following example:

+ +

(lldb) frame variable -T sp
+ (SimpleWithPointers) sp = {
+     (int *) x = 0x0000000100100120
+     (float *) y = + 0x0000000100100130
+     (char *) z = + 0x0000000100100140 "6"
+ }
+

+ +

However, in certain cases, you may want to associate a + different format to the display for certain datatypes. + To do so, you need to give hints to the debugger as to + how datatypes should be displayed.
+ A new type command has been introduced in LLDB + which allows to do just that.
+

+ +

Using it you can obtain a format like this one for sp, + instead of the default shown above:

+ +

(lldb) frame variable sp
+ (SimpleWithPointers) sp = + (x=0x0000000100100120 -> -1, y=0x0000000100100130 + -> -2, z="3")
+

+ +

There are two kinds of printing options: summary and format. While a + detailed description of both will be given below, one + can briefly say that a summary is mainly used for + aggregate types, while a format is attached to primitive + types.

+ +

To reflect this, the the type command has two + subcommands:
+

+ +

type format

+

type summary

+ +

These commands are meant to bind printing options to + types. When variables are printed, LLDB will first check + if custom printing options have been associated to a + variable's type and, if so, use them instead of picking + the default choices.
+

+ +

The two commands type format and type + summary each have four subcommands:
+

+

add: associates a new printing option to one + or more types

+

delete: deletes an existing association

+

list: provides a listing of all + associations

+

clear: deletes all associations

+
+
+ +
+

type format

+
+ +

Type formats enable you to quickly override the default + format for displaying primitive types (the usual basic + C/C++/ObjC types: int, float, char, ...).

+ +

If for some reason you want all int + variables in your program to print out as hex, you can add + a format to the int type.

+ +

This is done by typing type format add -f hex + int at the LLDB command line.

+ +

The -f option accepts a format name, and a list of + types to which you want the new format applied.

+ +

A frequent scenario is that your program has a typedef + for a numeric type that you know represents something + that must be printed in a certain way. Again, you can + add a format just to that typedef by using type + format add with the name alias.

+ +

But things can quickly get hierarchical. Let's say you + have a situation like the following:

+ +

typedef int A;
+ typedef A B;
+ typedef B C;
+ typedef C D;
+

+ +

and you want to show all A's as hex, all + C's as pointers and leave the defaults + untouched for other types.

+ +

If you simply type
+ type format add -f hex A
+ type format add -f pointer C

+
+ values of type B will be shown as hex + and values of type D as pointers.

+ +

This is because by default LLDB cascades + formats through typedef chains. In order to avoid that + you can use the option -C no to prevent + cascading, thus making the two commands required to + achieve your goal:
+ type format add -f hex -C no A
+ type format add -f pointer -C no C

+ +

Two additional options that you will want to look at + are -p and -r. These two + options prevent LLDB from applying a format for type T + to values of type T* and T& + respectively.

+ +

(lldb) type format add -f float32[] + int
+ (lldb) fr var pointer *pointer -T
+ (int *) pointer = {1.46991e-39 1.4013e-45}
+ (int) *pointer = {1.53302e-42}
+ (lldb) type format add -f float32[] int -p
+ (lldb) fr var pointer *pointer -T
+ (int *) pointer = 0x0000000100100180
+ (int) *pointer = {1.53302e-42}
+

+ +

As the previous example highlights, you will most + probably want to use -p for your formats.

+ +

If you need to delete a custom format simply type type + format delete followed by the name of the type + to which the format applies. To delete ALL formats, use + type format clear. To see all the formats + defined, type type format list.
+

+ +

If all you need to do, however, is display one variable + in a custom format, while leaving the others of the same + type untouched, you can simply type:
+
+ frame variable counter -f hex

+ +

This has the effect of displaying the value of counter + as an hexadecimal number, and will keep showing it this + way until you either pick a different format or till you + let your program run again.

+ +

Finally, this is a list of formatting options available + out of + which you can pick:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Format nameAbbreviationDescription
default
+
the default LLDB algorithm is used to pick a + format
booleanBshow this as a true/false boolean, using the + customary rule that 0 is false and everything else + is true
binarybshow this as a sequence of bits
bytesyshow the bytes one after the other
+ e.g. (int) s.x = 07 00 00 00
bytes with ASCIIYshow the bytes, but try to print them as ASCII + characters
+ e.g. (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 + 00 P.._....
charactercshow the bytes printed as ASCII characters
+ e.g. (int *) c.sp.x = + P\xf8\xbf_\xff\x7f\0\0
printable characterCshow the bytes printed as printable ASCII + characters
+ e.g. (int *) c.sp.x = P.._....
complex floatFinterpret this value as the real and imaginary + part of a complex floating-point number
+ e.g. (int *) c.sp.x = 2.76658e+19 + + 4.59163e-41i
c-stringsshow this as a 0-terminated C string
signed decimalishow this as a signed integer number (this does + not perform a cast, it simply shows the bytes as + signed integer)
enumerationEshow this as an enumeration, printing the + value's name if available or the integer value + otherwise
+ e.g. (enum enumType) val_type = eValue2
hexxshow this as in hexadecimal notation (this does + not perform a cast, it simply shows the bytes as + hex)
floatfshow this as a floating-point number (this does + not perform a cast, it simply interprets the bytes + as an IEEE754 floating-point value)
octaloshow this in octal notation
OSTypeOshow this as a MacOS OSType
+ e.g. (float) *c.sp.y = '\n\x1f\xd7\n'
unicode16Ushow this as UTF-16 characters
+ e.g. (float) *c.sp.y = 0xd70a 0x411f
unicode32
+
show this as UTF-32 characters
+ e.g. (float) *c.sp.y = 0x411fd70a
unsigned decimalushow this as an unsigned integer number (this + does not perform a cast, it simply shows the bytes + as unsigned integer)
pointerpshow this as a native pointer (unless this is + really a pointer, the resulting address will + probably be invalid)
char[]
+
show this as an array of characters
+ e.g. (char) *c.sp.z = {X}
int8_t[], uint8_t[]
+ int16_t[], uint16_t[]
+ int32_t[], uint32_t[]
+ int64_t[], uint64_t[]
+ uint128_t[]

+
show this as an array of the corresponding + integer type
+ e.g.
+ (int) sarray[0].x = {1 0 0 0}
+ (int) sarray[0].x = {0x00000001}
float32[], float64[]
+
show this as an array of the corresponding + floating-point type
+ e.g. (int *) pointer = {1.46991e-39 + 1.4013e-45}
complex integerIinterpret this value as the real and imaginary + part of a complex integer number
+ e.g. (int *) pointer = 1048960 + 1i
character arrayashow this as a character array
+ e.g. (int *) pointer = + \x80\x01\x10\0\x01\0\0\0
+
+
+ +
+

type summary

+
+

Type summaries enable you to add more information to + the default viewing format for a type, or to completely + replace it with your own display option. Unlike formats + which only apply to basic types, summaries can be used + on every type (basic types, classes (C++ and + Objective-C), arrays, ...).

+

The basic idea beneath type summaries is extracting + information from variables and arranging it in a format + that is suitable for display:

+

before adding a summary...
+ (lldb) fr var -T one
+ (i_am_cool) one = {
+ (int) integer = 3
+ (float) floating = 3.14159
+ (char) character = 'E'
+ }
+

+ after adding a summary...
+ (lldb) fr var one
+ (i_am_cool) one = int = 3, float = 3.14159, char = 69
+

+

Evidently, somehow we managed to tell LLDB to grab the + three member variables of the i_am_cool + datatype, mix their values with some text, and even ask + it to display the character member using a + custom format.

+

The way to do this is add a summary string to + the datatype using the type summary add + command.

+

Its syntax is similar to type format add, + but some more options are supported that will be + described in the follow-up.

+

The main option to type summary add is -f + which accepts as parameter a summary string. After that, + you can type as many type names as you want to associate + the given summary string to them.

+
+
+
+

Summary Strings

+
+

So what is the format of the summary strings? Summary + strings can contain plain text, control characters and + special symbols that have access to information about + the current object and the overall program state.

+

Normal characters are any text that doesn't contain a '{', + '}', '$', or '\' + character.

+

Variable names are found in between a "${" + prefix, and end with a "}" suffix. + In other words, a variable looks like "${frame.pc}".

+

Basically, all the variables described in Frame and Thread Formatting + are accepted. Also acceptable are the control characters + and scoping features described in that page. + Additionally, ${var and ${*var + become acceptable symbols in this scenario.

+

The simplest thing you can do is grab a member variable + of a class or structure by typing its expression + path. In the previous example, the expression path + for the floating member is simply .floating, + because all you have to do to get at it given an object + of type i_am_cool is access it straight + away. Thus, to ask the summary string to display floating + you would type ${var.floating} (${var + is a placeholder token replaced with whatever variable + is being displayed).

+

If you have code like the following:
+ struct A {
+ int x;
+ int y;
+ };
+ struct B {
+ A x;
+ A y;
+ int z;
+ };
+
the expression path for the y + member of the x member of an object of + type B would be .x.y and you + would type ${var.x.y} to display it in a + summary string for type B.

+

As you could be using a summary string for both + displaying objects of type T or T* + (unless -p is used to prevent this), the + expression paths do not differentiate between . + and ->, and the above expression path .x.y + would be just as good if you were displaying a B*, + or even if the actual definition of B + were:
+ struct B {
+ A *x;
+ A y;
+ int z;
+ };
+

+

This is unlike the behaviour of frame variable + which, on the contrary, will enforce the distinction. As + hinted above, the rationale for this choice is that + waiving this distinction enables one to write a summary + string once for type T and use it for both + T and T* instances. As a + summary string is mostly about extracting nested + members' information, a pointer to an object is just as + good as the object itself for the purpose.

+

Of course, you can have multiple entries in one summary + string. For instance, the command used to produce the + above summary string for i_am_cool was:
+ type summary add -f "int = ${var.integer}, float = + ${var.floating}, char = ${var.character%u}" i_am_cool +

+

As you can see, the last expression path also contains + a %u symbol which is nowhere to be found + in the actual member variable name. The symbol is + reminding of a printf() format symbol, and + in fact it has a similar effect. If you add a % sign + followed by any one format name or abbreviation from the + above table after an expression path, the resulting + object will be displyed using exactly that format + instead of the LLDB default one.

+

There are two more special format symbols that you can + use only as part of a summary string: %V + and %@. The first one tells LLDB to ignore + summary strings for the type of the object referred by + the expression path and instead print the object's + value. The second is only applicable to Objective-C + classes, and tells LLDB to get the object's description + from the Objective-C runtime. By default, if no format + is provided, LLDB will try to get the object's summary, + and if empty the object's value. If neither can be + obtained, nothing will be displayed.

+

As previously said, pointers and values are treated the + same way when getting to their members in an expression + path. However, if your expression path leads to a + pointer, LLDB will not automatically dereference it. In + order to obtain The deferenced value for a pointer, your + expression path must start with ${*var + instead of ${var. Because there is no need + to dereference pointers along your way, the + dereferencing symbol only applies to the result of the + whole expression path traversing.
+ e.g.
+ (lldb) fr var -T c
+ (Couple) c = {
+ (SimpleWithPointers) sp = {
+ (int *) x = 0x00000001001000b0
+ (float *) y = 0x00000001001000c0
+ (char *) z = 0x00000001001000d0 "X"
+ }
+ (Simple *) s = 0x00000001001000e0
+ }
+ (lldb) type summary add -f "int = ${*var.sp.x}, + float = ${*var.sp.y}, char = ${*var.sp.z%u}, Simple = + ${*var.s}" Couple
+ (lldb) type summary add -c -p Simple
+ (lldb) fr var c
+ (Couple) c = int = 9, float = 9.99, char = 88, Simple + = (x=9, y=9.99, z='X')
+

+

Option -c to type summary add + tells LLDB not to look for a summary string, but instead + to just print a listing of all the object's children on + one line, lay out as in the previous example. The -p + flag is used as a trick to show that aggregate types can + be dereferenced as well as primitive ones. The above + output would be shown even by typing type summary + add -f "int = ${*var.sp.x}, float = ${*var.sp.y}, char + = ${*var.sp.z%u}, Simple = ${var.s}" Couple if + one took away the -p flag from the summary + for type Simple.

+
+
+
+

More on summary strings

+
+

What was described above are the main features that you + can use in summary strings. However, there are three + more features to them.

+

Sometimes, a basic type's value actually represents + several different values packed together in a bitfield. + With the classical view, there is no way to look at + them. Hexadecimal display can help, but if the bits + actually span byte boundaries, the help is limited. + Binary view would show it all without ambiguity, but is + often too detailed and hard to read for real-life + scenarios. To cope with the issue, LLDB supports native + bitfield formatting in summary strings. If your + expression paths leads to a so-called scalar type + (the usual int, float, char, double, short, long, long + long, double, long double and unsigned variants), you + can ask LLDB to only grab some bits out of the value and + display them in any format you like. The syntax is + similar to that used for arrays, just you can also give + a pair of indices separated by a -.
+ e.g.
+ (lldb) fr var float_point
+ (float) float_point = -3.14159
+ (lldb) type summary add -f "Sign: ${var[31]%B} + Exponent: ${var[30-23]%x} Mantissa: ${var[0-22]%u}" + float
+ (lldb) fr var float_point
+ (float) float_point = -3.14159 Sign: true Exponent: + 0x00000080 Mantissa: 4788184
+
In this example, LLDB shows the internal + representation of a float variable by + extracting bitfields out of a float object. If you give + a single index, only that one bit will be extracted. If + you give a pair of indices, all the bits in the range + (extremes included) will be extracted. Ranges can be + specified either by giving the lower index first, or + higher index first (as is often customary in describing + packed data-type formats).

+

The second additional feature allows you to display + array members inside a summary string. For instance, you + may want to display all arrays of a given type using a + more compact notation than the default, and then just + delve into individual array members that prove + interesting to your debugging task. You can use a + similar syntax to the one used for bitfields to tell + LLDB to format arrays in special ways.
+ e.g.
+ (lldb) fr var sarray
+ (Simple [3]) sarray = {
+ [0] = {
+ x = 1
+ y = 2
+ z = '\x03'
+ }
+ [1] = {
+ x = 4
+ y = 5
+ z = '\x06'
+ }
+ [2] = {
+ x = 7
+ y = 8
+ z = '\t'
+ }
+ }
+ (lldb) type summary add -f "${var[].x}" "Simple + [3]"
+ (lldb) fr var sarray
+ (Simple [3]) sarray = [1,4,7]
+
The [] symbol amounts to: if var + is an array and I knows its size, apply this summary + string to every element of the array. Here, we are + asking LLDB to display .x for every + element of the array, and in fact this is what happens. + If you find some of those integers anomalous, you can + then inspect that one item in greater detail, without + the array format getting in the way:
+ (lldb) fr var sarray[1]
+ (Simple) sarray[1] = {
+ x = 4
+ y = 5
+ z = '\x06'
+ }
+

+

You can also ask LLDB to only print a subset of the + array range by using the same syntax used to extract bit + for bitfields.

+

The same logic works if you are printing a pointer + instead of an array, however in this latter case, [] + cannot be used and you need to give exact range limits.

+

The third, and last, additional feature does not + directly apply to the summary strings themselves, but is + an additional option to the type summary add + command: -x

+

As you noticed, in order to associate the custom + summary string to the array types, one must give the + array size as part of the typename. This can long become + tiresome when using arrays of different sizes, Simple + + [3], Simple [9], Simple + [12], ...

+

If you use the -x option, type names are + treated as regular expressions instead of type names. + This would let you rephrase the above example as:
+ (lldb) type summary add -f "${var[].x}" + -x "Simple \[[0-9]+\]"
+ (lldb) fr var sarray
+ (Simple [3]) sarray = [1,4,7]
+
The above scenario works for Simple [3] + as well as for any other array of Simple + objects.

+

While this feature is mostly useful for arrays, you + could also use regular expressions to catch other type + sets grouped by name. However, as regular expression + matching is slower than normal name matching, LLDB will + first try to match by name in any way it can, and only + when this fails, will it resort to regular expression + matching. Thus, if your type has a base class with a + cascading summary, this will be preferred over any + regular expression match for your type itself.

+
+
+
+

Finding summaries 101

+
+

While the rules for finding an appropriate format for a + type are relatively simple (just go through typedef + hierarchies), summaries follow a more complicated + process in finding the right summary string for a + variable. Namely, what happens is:

+
    +
  • If there is a summary for the type of the variable, + use it
  • +
  • If this object is a pointer, and there is a summary + for the pointee type that does not skip pointers, use + it
  • +
  • If this object is a reference, and there is a + summary for the pointee type that does not skip + references, use it
  • +
  • If this object is an Objective-C class with a parent + class, look at the parent class (and parent of parent, + ...)
  • +
  • If this object is a C++ class with base classes, + look at base classes (and bases of bases, ...)
  • +
  • If this object is a C++ class with virtual base + classes, look at the virtual base classes (and bases + of bases, ...)
  • +
  • If this object's type is a typedef, go through + typedef hierarchy
  • +
  • If everything has failed, repeat the above search, + looking for regular expressions instead of exact + matches
  • +
+
+
+
+

TODOs

+
+
    +
  • There's no way to do multiple dereferencing, and you + need to be careful what the dereferencing operation is + binding to in complicated scenarios
  • +
  • There is no way to call functions inside summary + strings, not even const ones
  • +
  • type format add does not support the -x + option
  • +
  • Object location cannot be printed in the summary + string
  • +
+
+
+
+
+
+ + From gclayton at apple.com Thu Jul 7 22:21:57 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 03:21:57 -0000 Subject: [Lldb-commits] [lldb] r134681 - in /lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel: DynamicLoaderMacOSXKernel.cpp DynamicLoaderMacOSXKernel.h Message-ID: <20110708032157.5A1CA2A6C12C@llvm.org> Author: gclayton Date: Thu Jul 7 22:21:57 2011 New Revision: 134681 URL: http://llvm.org/viewvc/llvm-project?rev=134681&view=rev Log: Make the kernel able to do its initial load from target memory with the process being preferred for all memory reads. Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp?rev=134681&r1=134680&r2=134681&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Thu Jul 7 22:21:57 2011 @@ -67,7 +67,7 @@ DynamicLoaderMacOSXKernel::DynamicLoaderMacOSXKernel (Process* process) : DynamicLoader(process), m_kernel(), - m_kext_summary_header_addr (LLDB_INVALID_ADDRESS), + m_kext_summary_header_addr (), m_kext_summary_header (), m_kext_summary_header_stop_id (0), m_break_id (LLDB_INVALID_BREAK_ID), @@ -129,7 +129,7 @@ if (clear_process) m_process = NULL; m_kernel.Clear(false); - m_kext_summary_header_addr = LLDB_INVALID_ADDRESS; + m_kext_summary_header_addr.Clear(); m_kext_summaries.clear(); m_kext_summaries_stop_id = 0; m_break_id = LLDB_INVALID_BREAK_ID; @@ -153,7 +153,7 @@ bool DynamicLoaderMacOSXKernel::LoadKernelModule() { - if (m_kext_summary_header_addr == LLDB_INVALID_ADDRESS) + if (!m_kext_summary_header_addr.IsValid()) { m_kernel.Clear(false); m_kernel.module_sp = m_process->GetTarget().GetExecutableModule(); @@ -163,9 +163,9 @@ const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute); if (symbol) { - m_kernel.address = symbol->GetValue().GetFileAddress(); + m_kernel.so_address = symbol->GetValue(); DataExtractor data; // Load command data - if (ReadMachHeader (m_kernel.address, &m_kernel.header, &data)) + if (ReadMachHeader (m_kernel, &data)) { if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) { @@ -366,77 +366,12 @@ //---------------------------------------------------------------------- bool DynamicLoaderMacOSXKernel::NotifyBreakpointHit (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id) -{ - // Let the event know that the images have changed - // DYLD passes three arguments to the notification breakpoint. - // Arg1: enum dyld_image_mode mode - 0 = adding, 1 = removing - // Arg2: uint32_t infoCount - Number of shared libraries added - // Arg3: dyld_image_info info[] - Array of structs of the form: - // const struct mach_header *imageLoadAddress - // const char *imageFilePath - // uintptr_t imageFileModDate (a time_t) - + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) +{ DynamicLoaderMacOSXKernel* dyld_instance = (DynamicLoaderMacOSXKernel*) baton; - // First step is to see if we've already initialized the all image infos. If we haven't then this function - // will do so and return true. In the course of initializing the all_image_infos it will read the complete - // current state, so we don't need to figure out what has changed from the data passed in to us. - - if (!dyld_instance->ReadAllKextSummaries(false)) - { - Process *process = context->exe_ctx.process; - const lldb::ABISP &abi = process->GetABI(); - if (abi != NULL) - { - // Build up the value array to store the three arguments given above, then get the values from the ABI: - - ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); - ValueList argument_values; - Value input_value; - - void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); - void *clang_uint32_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingUint, 32); - input_value.SetValueType (Value::eValueTypeScalar); - input_value.SetContext (Value::eContextTypeClangType, clang_uint32_type); - argument_values.PushValue(input_value); - argument_values.PushValue(input_value); - input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type); - argument_values.PushValue (input_value); - - if (abi->GetArgumentValues (*context->exe_ctx.thread, argument_values)) - { - uint32_t dyld_mode = argument_values.GetValueAtIndex(0)->GetScalar().UInt (-1); - if (dyld_mode != -1) - { - // Okay the mode was right, now get the number of elements, and the array of new elements... - uint32_t image_infos_count = argument_values.GetValueAtIndex(1)->GetScalar().UInt (-1); - if (image_infos_count != -1) - { - // Got the number added, now go through the array of added elements, putting out the mach header - // address, and adding the image. - // Note, I'm not putting in logging here, since the AddModules & RemoveModules functions do - // all the logging internally. - - lldb::addr_t kext_summary_addr = argument_values.GetValueAtIndex(2)->GetScalar().ULongLong(); - if (dyld_mode == 0) - { - // This is add: - dyld_instance->ParseKextSummaries (kext_summary_addr, image_infos_count); - } - else - { - // This is remove: - dyld_instance->RemoveModulesUsingImageInfosAddress (kext_summary_addr, image_infos_count); - } - - } - } - } - } - } // Return true to stop the target, false to just let the target run return dyld_instance->GetStopWhenImagesChange(); } @@ -451,7 +386,7 @@ return true; m_kext_summaries.clear(); - if (m_kext_summary_header_addr != LLDB_INVALID_ADDRESS) + if (m_kext_summary_header_addr.IsValid()) { const uint32_t addr_size = m_kernel.GetAddressByteSize (); const ByteOrder byte_order = m_kernel.GetByteOrder(); @@ -461,7 +396,8 @@ uint8_t buf[24]; DataExtractor data (buf, sizeof(buf), byte_order, addr_size); const size_t count = 4 * sizeof(uint32_t) + addr_size; - const size_t bytes_read = m_process->ReadMemory (m_kext_summary_header_addr, buf, count, error); + const bool prefer_file_cache = false; + const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error); if (bytes_read == count) { uint32_t offset = 0; @@ -478,7 +414,8 @@ bool -DynamicLoaderMacOSXKernel::ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count) +DynamicLoaderMacOSXKernel::ParseKextSummaries (const lldb_private::Address &kext_summary_addr, + uint32_t count) { OSKextLoadedKextSummary::collection kext_summaries; LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); @@ -497,7 +434,7 @@ if (!kext_summaries[i].UUIDValid()) { DataExtractor data; // Load command data - if (!ReadMachHeader (kext_summaries[i].address, &kext_summaries[i].header, &data)) + if (!ReadMachHeader (kext_summaries[i], &data)) continue; ParseLoadCommands (data, kext_summaries[i]); @@ -569,98 +506,9 @@ return true; } -bool -DynamicLoaderMacOSXKernel::RemoveModulesUsingImageInfosAddress (lldb::addr_t kext_summary_addr, uint32_t image_infos_count) -{ - OSKextLoadedKextSummary::collection image_infos; - LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); - - Mutex::Locker locker(m_mutex); - if (m_process->GetStopID() == m_kext_summaries_stop_id) - return true; - - // First read in the image_infos for the removed modules, and their headers & load commands. - if (!ReadKextSummaries (kext_summary_addr, image_infos_count, image_infos)) - { - if (log) - log->PutCString ("Failed reading image infos array."); - return false; - } - - if (log) - log->Printf ("Removing %d modules.", image_infos_count); - - ModuleList unloaded_module_list; - for (uint32_t idx = 0; idx < image_infos.size(); ++idx) - { - if (log) - { - log->Printf ("Removing module at address=0x%16.16llx.", image_infos[idx].address); - image_infos[idx].PutToLog (log.get()); - } - - // Remove this image_infos from the m_all_image_infos. We do the comparision by address - // rather than by file spec because we can have many modules with the same "file spec" in the - // case that they are modules loaded from memory. - // - // Also copy over the uuid from the old entry to the removed entry so we can - // use it to lookup the module in the module list. - - OSKextLoadedKextSummary::collection::iterator pos, end = m_kext_summaries.end(); - for (pos = m_kext_summaries.begin(); pos != end; pos++) - { - if (image_infos[idx].address == (*pos).address) - { - image_infos[idx].uuid = (*pos).uuid; - - // Add the module from this image_info to the "unloaded_module_list". We'll remove them all at - // one go later on. - - if (FindTargetModule (image_infos[idx], false, NULL)) - { - UnloadImageLoadAddress (image_infos[idx]); - unloaded_module_list.AppendIfNeeded (image_infos[idx].module_sp); - } - else - { - if (log) - { - log->Printf ("Could not find module for unloading info entry:"); - image_infos[idx].PutToLog(log.get()); - } - } - - // Then remove it from the m_kext_summaries: - - m_kext_summaries.erase(pos); - break; - } - } - - if (pos == end) - { - if (log) - { - log->Printf ("Could not find image_info entry for unloading image:"); - image_infos[idx].PutToLog(log.get()); - } - } - } - if (unloaded_module_list.GetSize() > 0) - { - if (log) - { - log->PutCString("Unloaded:"); - unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXKernel::ModulesDidUnload"); - } - m_process->GetTarget().ModulesDidUnload (unloaded_module_list); - } - m_kext_summaries_stop_id = m_process->GetStopID(); - return true; -} uint32_t -DynamicLoaderMacOSXKernel::ReadKextSummaries (lldb::addr_t kext_summary_addr, +DynamicLoaderMacOSXKernel::ReadKextSummaries (const lldb_private::Address &kext_summary_addr, uint32_t image_infos_count, OSKextLoadedKextSummary::collection &image_infos) { @@ -671,10 +519,12 @@ const size_t count = image_infos.size() * m_kext_summary_header.entry_size; DataBufferHeap data(count, 0); Error error; - const size_t bytes_read = m_process->ReadMemory (kext_summary_addr, - data.GetBytes(), - data.GetByteSize(), - error); + const bool prefer_file_cache = false; + const size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary_addr, + prefer_file_cache, + data.GetBytes(), + data.GetByteSize(), + error); if (bytes_read == count) { uint32_t offset = 0; @@ -688,6 +538,8 @@ memcpy (image_infos[i].name, name_data, KERNEL_MODULE_MAX_NAME); image_infos[i].uuid.SetBytes(extractor.GetData (&offset, 16)); image_infos[i].address = extractor.GetU64(&offset); + if (!image_infos[i].so_address.SetLoadAddress (image_infos[i].address, &m_process->GetTarget())) + m_process->GetTarget().GetImages().ResolveFileAddress (image_infos[i].address, image_infos[i].so_address); image_infos[i].size = extractor.GetU64(&offset); image_infos[i].version = extractor.GetU64(&offset); image_infos[i].load_tag = extractor.GetU32(&offset); @@ -720,7 +572,9 @@ { if (m_kext_summary_header.entry_count > 0) { - if (!ParseKextSummaries (m_kext_summary_header_addr + 16, m_kext_summary_header.entry_count)) + Address summary_addr (m_kext_summary_header_addr); + summary_addr.Slide(16); + if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count)) { DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); m_kext_summaries.clear(); @@ -738,36 +592,38 @@ // Returns true if we succeed, false if we fail for any reason. //---------------------------------------------------------------------- bool -DynamicLoaderMacOSXKernel::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, DataExtractor *load_command_data) +DynamicLoaderMacOSXKernel::ReadMachHeader (OSKextLoadedKextSummary& kext_summary, DataExtractor *load_command_data) { DataBufferHeap header_bytes(sizeof(llvm::MachO::mach_header), 0); Error error; - size_t bytes_read = m_process->ReadMemory (addr, - header_bytes.GetBytes(), - header_bytes.GetByteSize(), - error); + const bool prefer_file_cache = false; + size_t bytes_read = m_process->GetTarget().ReadMemory (kext_summary.so_address, + prefer_file_cache, + header_bytes.GetBytes(), + header_bytes.GetByteSize(), + error); if (bytes_read == sizeof(llvm::MachO::mach_header)) { uint32_t offset = 0; - ::memset (header, 0, sizeof(header)); + ::memset (&kext_summary.header, 0, sizeof(kext_summary.header)); // Get the magic byte unswapped so we can figure out what we are dealing with DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4); - header->magic = data.GetU32(&offset); - lldb::addr_t load_cmd_addr = addr; - data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(header->magic)); - switch (header->magic) + kext_summary.header.magic = data.GetU32(&offset); + Address load_cmd_addr = kext_summary.so_address; + data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(kext_summary.header.magic)); + switch (kext_summary.header.magic) { case llvm::MachO::HeaderMagic32: case llvm::MachO::HeaderMagic32Swapped: data.SetAddressByteSize(4); - load_cmd_addr += sizeof(llvm::MachO::mach_header); + load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header)); break; case llvm::MachO::HeaderMagic64: case llvm::MachO::HeaderMagic64Swapped: data.SetAddressByteSize(8); - load_cmd_addr += sizeof(llvm::MachO::mach_header_64); + load_cmd_addr.Slide (sizeof(llvm::MachO::mach_header_64)); break; default: @@ -775,23 +631,24 @@ } // Read the rest of dyld's mach header - if (data.GetU32(&offset, &header->cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1)) + if (data.GetU32(&offset, &kext_summary.header.cputype, (sizeof(llvm::MachO::mach_header)/sizeof(uint32_t)) - 1)) { if (load_command_data == NULL) return true; // We were able to read the mach_header and weren't asked to read the load command bytes - DataBufferSP load_cmd_data_sp(new DataBufferHeap(header->sizeofcmds, 0)); + DataBufferSP load_cmd_data_sp(new DataBufferHeap(kext_summary.header.sizeofcmds, 0)); - size_t load_cmd_bytes_read = m_process->ReadMemory (load_cmd_addr, - load_cmd_data_sp->GetBytes(), - load_cmd_data_sp->GetByteSize(), - error); + size_t load_cmd_bytes_read = m_process->GetTarget().ReadMemory (load_cmd_addr, + prefer_file_cache, + load_cmd_data_sp->GetBytes(), + load_cmd_data_sp->GetByteSize(), + error); - if (load_cmd_bytes_read == header->sizeofcmds) + if (load_cmd_bytes_read == kext_summary.header.sizeofcmds) { // Set the load command data and also set the correct endian // swap settings and the correct address size - load_command_data->SetData(load_cmd_data_sp, 0, header->sizeofcmds); + load_command_data->SetData(load_cmd_data_sp, 0, kext_summary.header.sizeofcmds); load_command_data->SetByteOrder(data.GetByteOrder()); load_command_data->SetAddressByteSize(data.GetAddressByteSize()); return true; // We successfully read the mach_header and the load command data @@ -997,7 +854,7 @@ Mutex::Locker locker(m_mutex); log->Printf("gLoadedKextSummaries = 0x%16.16llx { version=%u, entry_size=%u, entry_count=%u, reserved=%u }", - m_kext_summary_header_addr, + m_kext_summary_header_addr.GetFileAddress(), m_kext_summary_header.version, m_kext_summary_header.entry_size, m_kext_summary_header.entry_count, Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h?rev=134681&r1=134680&r2=134681&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Thu Jul 7 22:21:57 2011 @@ -148,10 +148,6 @@ return lldb::eByteOrderInvalid; } - bool - ReadMachHeader (lldb::addr_t addr, - llvm::MachO::mach_header *header, - lldb_private::DataExtractor *load_command_data); class Segment { public: @@ -198,6 +194,7 @@ char name[KERNEL_MODULE_MAX_NAME]; lldb::ModuleSP module_sp; lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros + lldb_private::Address so_address; // The section offset address for this kext in case it can be read from object files uint64_t address; uint64_t size; uint64_t version; @@ -210,6 +207,7 @@ OSKextLoadedKextSummary() : module_sp (), uuid (), + so_address (), address (LLDB_INVALID_ADDRESS), size (0), version (0), @@ -227,6 +225,7 @@ { if (!load_cmd_data_only) { + so_address.Clear(); address = LLDB_INVALID_ADDRESS; size = 0; version = 0; @@ -349,6 +348,10 @@ } }; + bool + ReadMachHeader (OSKextLoadedKextSummary& kext_summary, + lldb_private::DataExtractor *load_command_data); + void RegisterNotificationCallbacks(); @@ -377,14 +380,12 @@ ReadKextSummaryHeader (); bool - ParseKextSummaries (lldb::addr_t kext_summary_addr, uint32_t count); + ParseKextSummaries (const lldb_private::Address &kext_summary_addr, + uint32_t count); bool AddModulesUsingImageInfos (OSKextLoadedKextSummary::collection &image_infos); - bool - RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); - void UpdateImageInfosHeaderAndLoadCommands(OSKextLoadedKextSummary::collection &image_infos, uint32_t infos_count, @@ -394,7 +395,7 @@ UpdateCommPageLoadAddress (lldb_private::Module *module); uint32_t - ReadKextSummaries (lldb::addr_t image_infos_addr, + ReadKextSummaries (const lldb_private::Address &kext_summary_addr, uint32_t image_infos_count, OSKextLoadedKextSummary::collection &image_infos); @@ -402,7 +403,7 @@ UnloadImageLoadAddress (OSKextLoadedKextSummary& info); OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used - lldb::addr_t m_kext_summary_header_addr; + lldb_private::Address m_kext_summary_header_addr; OSKextLoadedKextSummaryHeader m_kext_summary_header; uint32_t m_kext_summary_header_stop_id; // The process stop ID that "m_kext_summary_header" is valid for lldb::user_id_t m_break_id; From gclayton at apple.com Thu Jul 7 23:11:42 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 04:11:42 -0000 Subject: [Lldb-commits] [lldb] r134682 - in /lldb/trunk/source: Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h lldb.cpp Message-ID: <20110708041142.660CE2A6C12C@llvm.org> Author: gclayton Date: Thu Jul 7 23:11:42 2011 New Revision: 134682 URL: http://llvm.org/viewvc/llvm-project?rev=134682&view=rev Log: LLDB now has a Kernel dynamic linker that can detect where kexts are loaded. It locks onto *-apple-darwin binaries where the binary has a "__KLD" segment. Soon I will modify the lldb_private::ObjectFile class to return an executable type which will be an enum with values something like: eObjectFileTypeUserExectable, eObjectFileTypeUserSharedLibrary, eObjectFileTypeKernelExectable, eObjectFileTypeKernelSharedLibrary, eObjectFileTypeObjectFile, eObjectFileTypeCoreFile But for now we look at the section since a user and kernel mach-o executable have the same mach-o file type. Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h lldb/trunk/source/lldb.cpp Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=134682&r1=134681&r2=134682&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Thu Jul 7 23:11:42 2011 @@ -88,9 +88,30 @@ bool create = force; if (!create) { - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); - if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple) - create = true; + create = true; + Module* exe_module = process->GetTarget().GetExecutableModule().get(); + if (exe_module) + { + ObjectFile *object_file = exe_module->GetObjectFile(); + if (object_file) + { + SectionList *section_list = object_file->GetSectionList(); + if (section_list) + { + static ConstString g_kld_section_name ("__KLD"); + if (section_list->FindSectionByName (g_kld_section_name)) + { + create = false; + } + } + } + } + + if (create) + { + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); + create = triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple; + } } if (create) Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp?rev=134682&r1=134681&r2=134682&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Thu Jul 7 23:11:42 2011 @@ -51,9 +51,29 @@ bool create = force; if (!create) { - const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); - if (triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple) - create = true; + Module* exe_module = process->GetTarget().GetExecutableModule().get(); + if (exe_module) + { + ObjectFile *object_file = exe_module->GetObjectFile(); + if (object_file) + { + SectionList *section_list = object_file->GetSectionList(); + if (section_list) + { + static ConstString g_kld_section_name ("__KLD"); + if (section_list->FindSectionByName (g_kld_section_name)) + { + create = true; + } + } + } + } + + if (create) + { + const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple(); + create = triple_ref.getOS() == llvm::Triple::Darwin && triple_ref.getVendor() == llvm::Triple::Apple; + } } if (create) @@ -160,14 +180,22 @@ if (m_kernel.module_sp) { static ConstString mach_header_name ("_mh_execute_header"); - const Symbol *symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute); + static ConstString kext_summary_symbol ("gLoadedKextSummaries"); + const Symbol *symbol = NULL; + symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (kext_summary_symbol, eSymbolTypeData); + if (symbol) + m_kext_summary_header_addr = symbol->GetValue(); + + symbol = m_kernel.module_sp->FindFirstSymbolWithNameAndType (mach_header_name, eSymbolTypeAbsolute); if (symbol) { - m_kernel.so_address = symbol->GetValue(); + // The "_mh_execute_header" symbol is absolute and not a section based + // symbol that will have a valid address, so we need to resolve it... + m_process->GetTarget().GetImages().ResolveFileAddress (symbol->GetValue().GetFileAddress(), m_kernel.so_address); DataExtractor data; // Load command data if (ReadMachHeader (m_kernel, &data)) { - if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeDynamicLinkEditor) + if (m_kernel.header.filetype == llvm::MachO::HeaderFileTypeExecutable) { if (ParseLoadCommands (data, m_kernel)) UpdateImageLoadAddress (m_kernel); @@ -665,16 +693,16 @@ // Parse the load commands for an image //---------------------------------------------------------------------- uint32_t -DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& dylib_info) +DynamicLoaderMacOSXKernel::ParseLoadCommands (const DataExtractor& data, OSKextLoadedKextSummary& image_info) { uint32_t offset = 0; uint32_t cmd_idx; Segment segment; - dylib_info.Clear (true); + image_info.Clear (true); - for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) + for (cmd_idx = 0; cmd_idx < image_info.header.ncmds; cmd_idx++) { - // Clear out any load command specific data from DYLIB_INFO since + // Clear out any load command specific data from image_info since // we are about to read it. if (data.ValidOffsetForDataOfSize (offset, sizeof(llvm::MachO::load_command))) @@ -696,7 +724,7 @@ segment.filesize = data.GetU32 (&offset); // Extract maxprot, initprot, nsects and flags all at once data.GetU32(&offset, &segment.maxprot, 4); - dylib_info.segments.push_back (segment); + image_info.segments.push_back (segment); } break; @@ -707,12 +735,12 @@ data.GetU64(&offset, &segment.vmaddr, 4); // Extract maxprot, initprot, nsects and flags all at once data.GetU32(&offset, &segment.maxprot, 4); - dylib_info.segments.push_back (segment); + image_info.segments.push_back (segment); } break; case llvm::MachO::LoadCommandUUID: - dylib_info.uuid.SetBytes(data.GetData (&offset, 16)); + image_info.uuid.SetBytes(data.GetData (&offset, 16)); break; default: @@ -732,21 +760,30 @@ // that is greater than zero) in the object file. // Determine the slide amount (if any) - const size_t num_sections = dylib_info.segments.size(); + const size_t num_sections = image_info.segments.size(); for (size_t i = 0; i < num_sections; ++i) { // Iterate through the object file sections to find the // first section that starts of file offset zero and that // has bytes in the file... - if (dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0) + if (image_info.segments[i].fileoff == 0 && image_info.segments[i].filesize > 0) { - dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr; + image_info.slide = image_info.address - image_info.segments[i].vmaddr; // We have found the slide amount, so we can exit // this for loop. break; } } #endif + if (image_info.uuid.IsValid()) + { + bool did_create = false; + if (FindTargetModule(image_info, true, &did_create)) + { + if (did_create) + image_info.module_create_stop_id = m_process->GetStopID(); + } + } return cmd_idx; } Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h?rev=134682&r1=134681&r2=134682&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Thu Jul 7 23:11:42 2011 @@ -193,6 +193,7 @@ { char name[KERNEL_MODULE_MAX_NAME]; lldb::ModuleSP module_sp; + uint32_t module_create_stop_id; lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros lldb_private::Address so_address; // The section offset address for this kext in case it can be read from object files uint64_t address; @@ -206,6 +207,7 @@ OSKextLoadedKextSummary() : module_sp (), + module_create_stop_id (UINT32_MAX), uuid (), so_address (), address (LLDB_INVALID_ADDRESS), @@ -236,6 +238,7 @@ ::memset (&header, 0, sizeof(header)); } module_sp.reset(); + module_create_stop_id = UINT32_MAX; uuid.Clear(); segments.clear(); } Modified: lldb/trunk/source/lldb.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=134682&r1=134681&r2=134682&view=diff ============================================================================== --- lldb/trunk/source/lldb.cpp (original) +++ lldb/trunk/source/lldb.cpp Thu Jul 7 23:11:42 2011 @@ -38,6 +38,7 @@ #if defined (__APPLE__) #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h" +#include "Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h" #include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h" #include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h" @@ -94,6 +95,7 @@ // Apple/Darwin hosted plugins //---------------------------------------------------------------------- DynamicLoaderMacOSXDYLD::Initialize(); + DynamicLoaderMacOSXKernel::Initialize(); SymbolFileDWARFDebugMap::Initialize(); ItaniumABILanguageRuntime::Initialize(); AppleObjCRuntimeV2::Initialize(); @@ -158,6 +160,7 @@ #if defined (__APPLE__) DynamicLoaderMacOSXDYLD::Terminate(); + DynamicLoaderMacOSXKernel::Terminate(); SymbolFileDWARFDebugMap::Terminate(); ItaniumABILanguageRuntime::Terminate(); AppleObjCRuntimeV2::Terminate(); From jmolenda at apple.com Fri Jul 8 00:04:01 2011 From: jmolenda at apple.com (Jason Molenda) Date: Fri, 08 Jul 2011 05:04:01 -0000 Subject: [Lldb-commits] [lldb] r134686 - /lldb/trunk/tools/darwin-threads/examine-threads.c Message-ID: <20110708050401.6A6752A6C12C@llvm.org> Author: jmolenda Date: Fri Jul 8 00:04:01 2011 New Revision: 134686 URL: http://llvm.org/viewvc/llvm-project?rev=134686&view=rev Log: Rewrite get_kinfo_proc_for_pid() to get the kinfo_proc for the one process we're interested in, instead of fetching all of them and only keeping one. (the old implementation made sense when we were doing the initial find-this-process-by-pid-or-name by looking through all the kinfo_procs.) Modified: lldb/trunk/tools/darwin-threads/examine-threads.c Modified: lldb/trunk/tools/darwin-threads/examine-threads.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/darwin-threads/examine-threads.c?rev=134686&r1=134685&r2=134686&view=diff ============================================================================== --- lldb/trunk/tools/darwin-threads/examine-threads.c (original) +++ lldb/trunk/tools/darwin-threads/examine-threads.c Fri Jul 8 00:04:01 2011 @@ -96,33 +96,16 @@ struct kinfo_proc * get_kinfo_proc_for_pid (pid_t pid, const char *process_name) { - struct kinfo_proc *all_kinfos; - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; - size_t len; - if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0) + struct kinfo_proc *kinfo = (struct kinfo_proc *) malloc (sizeof (struct kinfo_proc)); + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; + size_t len = sizeof (struct kinfo_proc); + if (sysctl (mib, sizeof (mib) / sizeof (mib[0]), kinfo, &len, NULL, 0) != 0) { - printf ("Could not number of processes\n"); + free ((void *) kinfo); + printf ("Could not get kinfo_proc for pid %d\n", (int) pid); exit (1); } - all_kinfos = (struct kinfo_proc *) malloc (len); - if (sysctl (mib, 3, all_kinfos, &len, NULL, 0) != 0) - { - printf ("Could not get process infos\n"); - exit (1); - } - - int proc_count, i; - proc_count = len / sizeof (struct kinfo_proc); - for (i = 0 ; i < proc_count; i++) - if (all_kinfos[i].kp_proc.p_pid == pid) - { - struct kinfo_proc *kinfo = (struct kinfo_proc *) malloc (sizeof (struct kinfo_proc)); - memcpy (kinfo, &all_kinfos[i], sizeof (struct kinfo_proc)); - free ((void *) all_kinfos); - return kinfo; - } - printf ("Did not find process '%s' when re-getting proc table.\n", process_name); - exit (1); + return kinfo; } /* Get the basic information (thread_basic_info_t) about a given From gclayton at apple.com Fri Jul 8 13:16:51 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 18:16:51 -0000 Subject: [Lldb-commits] [lldb] r134713 - /lldb/tags/lldb-69/ Message-ID: <20110708181651.610272A6C12C@llvm.org> Author: gclayton Date: Fri Jul 8 13:16:51 2011 New Revision: 134713 URL: http://llvm.org/viewvc/llvm-project?rev=134713&view=rev Log: Copying lldb-68 to to prepare lldb-69 for submission. Added: lldb/tags/lldb-69/ - copied from r134712, lldb/tags/lldb-68/ From gclayton at apple.com Fri Jul 8 13:27:39 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 18:27:39 -0000 Subject: [Lldb-commits] [lldb] r134715 - in /lldb/trunk/source: Expression/ClangExpressionDeclMap.cpp Symbol/ClangASTContext.cpp Message-ID: <20110708182739.34A8C2A6C12C@llvm.org> Author: gclayton Date: Fri Jul 8 13:27:39 2011 New Revision: 134715 URL: http://llvm.org/viewvc/llvm-project?rev=134715&view=rev Log: Fixed a few issues where typedefs weren't passing through to the correct recursive function. Also fixed ClangASTContext::IsPointerType to correctly NULL out the pointee handle if a valid one is provided. Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp lldb/trunk/source/Symbol/ClangASTContext.cpp Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=134715&r1=134714&r2=134715&view=diff ============================================================================== --- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original) +++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Fri Jul 8 13:27:39 2011 @@ -1919,6 +1919,7 @@ if (!ClangASTContext::IsPointerType(self_user_type.GetOpaqueQualType(), &pointer_target_type)) + || pointer_target_type == NULL) return; TypeFromUser class_user_type(pointer_target_type, Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=134715&r1=134714&r2=134715&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Fri Jul 8 13:27:39 2011 @@ -4087,7 +4087,7 @@ break; case clang::Type::Typedef: - return ClangASTContext::IsPossibleCPlusPlusDynamicType (ast, cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type); + return ClangASTContext::IsPossibleDynamicType (ast, cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type); default: break; @@ -4382,8 +4382,11 @@ } bool -ClangASTContext::IsPointerType (clang_type_t clang_type, clang_type_t*target_type) +ClangASTContext::IsPointerType (clang_type_t clang_type, clang_type_t *target_type) { + if (target_type) + *target_type = NULL; + if (clang_type) { QualType qual_type (QualType::getFromOpaquePtr(clang_type)); @@ -4417,7 +4420,7 @@ *target_type = cast(qual_type)->getPointeeType().getAsOpaquePtr(); return true; case clang::Type::Typedef: - return ClangASTContext::IsPointerOrReferenceType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), target_type); + return ClangASTContext::IsPointerType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), target_type); default: break; } From gclayton at apple.com Fri Jul 8 13:29:48 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 18:29:48 -0000 Subject: [Lldb-commits] [lldb] r134716 - in /lldb/tags/lldb-69/source: Expression/ClangExpressionDeclMap.cpp Symbol/ClangASTContext.cpp Message-ID: <20110708182948.E81CA2A6C12C@llvm.org> Author: gclayton Date: Fri Jul 8 13:29:48 2011 New Revision: 134716 URL: http://llvm.org/viewvc/llvm-project?rev=134716&view=rev Log: Fixed for crashing during ASTImport due to bad pointers. Modified: lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp lldb/tags/lldb-69/source/Symbol/ClangASTContext.cpp Modified: lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp?rev=134716&r1=134715&r2=134716&view=diff ============================================================================== --- lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp (original) +++ lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp Fri Jul 8 13:29:48 2011 @@ -552,6 +552,9 @@ else return false; + if (!func_so_addr || !func_so_addr->IsValid()) + return false; + func_addr = func_so_addr->GetCallableLoadAddress (m_parser_vars->m_exe_ctx->target); return true; @@ -573,6 +576,10 @@ sc_list.GetContextAtIndex(i, sym_ctx); const Address *sym_address = &sym_ctx.symbol->GetAddressRangeRef().GetBaseAddress(); + + if (!sym_address || !sym_address->IsValid()) + return LLDB_INVALID_ADDRESS; + if (sym_address) { switch (sym_ctx.symbol->GetType()) @@ -1261,7 +1268,7 @@ NULL)); } else if (sym) - { + { location_value.reset(new Value); addr_t location_load_addr = GetSymbolAddress(*exe_ctx.target, name); @@ -1591,6 +1598,11 @@ var_sp = program_globals.GetVariableAtIndex (0); } } + + if (!var_sp || + !var_sp->IsInScope(&frame) || + !var_sp->LocationIsValidForFrame (&frame)) + return lldb::VariableSP(); if (var_sp && type) { @@ -1672,8 +1684,8 @@ if (const NamespaceDecl *namespace_decl = dyn_cast(context_decl)) { - Decl *original_decl; - ASTContext *original_ctx; + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; if (log) log->Printf("Resolving the containing context's origin..."); @@ -1705,7 +1717,7 @@ DeclContextLookupConstResult original_lookup_result = original_ctx->getExternalSource()->FindExternalVisibleDeclsByName(original_decl_context, context.m_decl_name); - NamedDecl *const *iter; + NamedDecl *const *iter = NULL; for (iter = original_lookup_result.first; iter != original_lookup_result.second; @@ -1854,7 +1866,7 @@ m_struct_vars->m_object_pointer_type = this_user_type; - void *pointer_target_type; + void *pointer_target_type = NULL; if (!ClangASTContext::IsPointerType(this_user_type.GetOpaqueQualType(), &pointer_target_type)) @@ -1903,10 +1915,11 @@ m_struct_vars->m_object_pointer_type = self_user_type; - void *pointer_target_type; + void *pointer_target_type = NULL; if (!ClangASTContext::IsPointerType(self_user_type.GetOpaqueQualType(), &pointer_target_type)) + || pointer_target_type == NULL) return; TypeFromUser class_user_type(pointer_target_type, @@ -2063,7 +2076,7 @@ return NULL; } - void *type_to_use; + void *type_to_use = NULL; if (parser_ast_context) { @@ -2383,9 +2396,9 @@ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - NamedDecl *fun_decl; + NamedDecl *fun_decl = NULL; std::auto_ptr fun_location(new Value); - const Address *fun_address; + const Address *fun_address = NULL; // only valid for Functions, not for Symbols void *fun_opaque_type = NULL; Modified: lldb/tags/lldb-69/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-69/source/Symbol/ClangASTContext.cpp?rev=134716&r1=134715&r2=134716&view=diff ============================================================================== --- lldb/tags/lldb-69/source/Symbol/ClangASTContext.cpp (original) +++ lldb/tags/lldb-69/source/Symbol/ClangASTContext.cpp Fri Jul 8 13:29:48 2011 @@ -4087,7 +4087,7 @@ break; case clang::Type::Typedef: - return ClangASTContext::IsPossibleCPlusPlusDynamicType (ast, cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type); + return ClangASTContext::IsPossibleDynamicType (ast, cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), dynamic_pointee_type); default: break; @@ -4382,8 +4382,11 @@ } bool -ClangASTContext::IsPointerType (clang_type_t clang_type, clang_type_t*target_type) +ClangASTContext::IsPointerType (clang_type_t clang_type, clang_type_t *target_type) { + if (target_type) + *target_type = NULL; + if (clang_type) { QualType qual_type (QualType::getFromOpaquePtr(clang_type)); @@ -4417,7 +4420,7 @@ *target_type = cast(qual_type)->getPointeeType().getAsOpaquePtr(); return true; case clang::Type::Typedef: - return ClangASTContext::IsPointerOrReferenceType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), target_type); + return ClangASTContext::IsPointerType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), target_type); default: break; } From jingham at apple.com Fri Jul 8 13:34:32 2011 From: jingham at apple.com (Jim Ingham) Date: Fri, 08 Jul 2011 18:34:32 -0000 Subject: [Lldb-commits] [lldb] r134717 - /lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Message-ID: <20110708183432.63DEC2A6C12C@llvm.org> Author: jingham Date: Fri Jul 8 13:34:32 2011 New Revision: 134717 URL: http://llvm.org/viewvc/llvm-project?rev=134717&view=rev Log: remove errant parenthesis. Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=134717&r1=134716&r2=134717&view=diff ============================================================================== --- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original) +++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Fri Jul 8 13:34:32 2011 @@ -1918,7 +1918,7 @@ void *pointer_target_type = NULL; if (!ClangASTContext::IsPointerType(self_user_type.GetOpaqueQualType(), - &pointer_target_type)) + &pointer_target_type) || pointer_target_type == NULL) return; From gclayton at apple.com Fri Jul 8 13:38:29 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 18:38:29 -0000 Subject: [Lldb-commits] [lldb] r134718 - /lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp Message-ID: <20110708183829.7C7072A6C12C@llvm.org> Author: gclayton Date: Fri Jul 8 13:38:29 2011 New Revision: 134718 URL: http://llvm.org/viewvc/llvm-project?rev=134718&view=rev Log: Fix manual merge compile error. Manual source merge == bad idea. Modified: lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp Modified: lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp?rev=134718&r1=134717&r2=134718&view=diff ============================================================================== --- lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp (original) +++ lldb/tags/lldb-69/source/Expression/ClangExpressionDeclMap.cpp Fri Jul 8 13:38:29 2011 @@ -1918,7 +1918,7 @@ void *pointer_target_type = NULL; if (!ClangASTContext::IsPointerType(self_user_type.GetOpaqueQualType(), - &pointer_target_type)) + &pointer_target_type) || pointer_target_type == NULL) return; From gclayton at apple.com Fri Jul 8 15:00:40 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 20:00:40 -0000 Subject: [Lldb-commits] [lldb] r134724 - in /lldb/tags/lldb-69: lldb.xcodeproj/project.pbxproj resources/LLDB-Info.plist Message-ID: <20110708200040.85F7F2A6C12C@llvm.org> Author: gclayton Date: Fri Jul 8 15:00:40 2011 New Revision: 134724 URL: http://llvm.org/viewvc/llvm-project?rev=134724&view=rev Log: lldb-69 Modified: lldb/tags/lldb-69/lldb.xcodeproj/project.pbxproj lldb/tags/lldb-69/resources/LLDB-Info.plist Modified: lldb/tags/lldb-69/lldb.xcodeproj/project.pbxproj URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-69/lldb.xcodeproj/project.pbxproj?rev=134724&r1=134723&r2=134724&view=diff ============================================================================== --- lldb/tags/lldb-69/lldb.xcodeproj/project.pbxproj (original) +++ lldb/tags/lldb-69/lldb.xcodeproj/project.pbxproj Fri Jul 8 15:00:40 2011 @@ -3418,10 +3418,10 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEBUG_INFORMATION_FORMAT = dwarf; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 68; + DYLIB_CURRENT_VERSION = 69; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3470,11 +3470,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 68; + DYLIB_CURRENT_VERSION = 69; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3521,8 +3521,8 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 68; - DYLIB_CURRENT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; + DYLIB_CURRENT_VERSION = 69; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3560,9 +3560,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 68; + DYLIB_CURRENT_VERSION = 69; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3600,9 +3600,9 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_CURRENT_VERSION = 68; + DYLIB_CURRENT_VERSION = 69; EXECUTABLE_EXTENSION = a; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3670,7 +3670,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3701,11 +3701,11 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 68; + DYLIB_CURRENT_VERSION = 69; EXPORTED_SYMBOLS_FILE = "resources/lldb-framework-exports"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3830,7 +3830,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEBUG_INFORMATION_FORMAT = dwarf; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -3862,7 +3862,7 @@ isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 68; + CURRENT_PROJECT_VERSION = 69; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", Modified: lldb/tags/lldb-69/resources/LLDB-Info.plist URL: http://llvm.org/viewvc/llvm-project/lldb/tags/lldb-69/resources/LLDB-Info.plist?rev=134724&r1=134723&r2=134724&view=diff ============================================================================== --- lldb/tags/lldb-69/resources/LLDB-Info.plist (original) +++ lldb/tags/lldb-69/resources/LLDB-Info.plist Fri Jul 8 15:00:40 2011 @@ -17,7 +17,7 @@ CFBundleSignature ???? CFBundleVersion - 68 + 69 CFBundleName ${EXECUTABLE_NAME} From jingham at apple.com Fri Jul 8 15:48:48 2011 From: jingham at apple.com (Jim Ingham) Date: Fri, 08 Jul 2011 20:48:48 -0000 Subject: [Lldb-commits] [lldb] r134736 - in /lldb/trunk/test/lang/objc/objc-static-method: ./ Makefile TestObjCStaticMethod.py static.m Message-ID: <20110708204848.154082A6C12C@llvm.org> Author: jingham Date: Fri Jul 8 15:48:47 2011 New Revision: 134736 URL: http://llvm.org/viewvc/llvm-project?rev=134736&view=rev Log: New test to check that we can call functions in static methods in ObjC. Added: lldb/trunk/test/lang/objc/objc-static-method/ lldb/trunk/test/lang/objc/objc-static-method/Makefile lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py lldb/trunk/test/lang/objc/objc-static-method/static.m Added: lldb/trunk/test/lang/objc/objc-static-method/Makefile URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-static-method/Makefile?rev=134736&view=auto ============================================================================== --- lldb/trunk/test/lang/objc/objc-static-method/Makefile (added) +++ lldb/trunk/test/lang/objc/objc-static-method/Makefile Fri Jul 8 15:48:47 2011 @@ -0,0 +1,6 @@ +LEVEL = ../../../make + +OBJC_SOURCES := static.m +LDFLAGS = $(CFLAGS) -lobjc -framework Foundation + +include $(LEVEL)/Makefile.rules Added: lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py?rev=134736&view=auto ============================================================================== --- lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py (added) +++ lldb/trunk/test/lang/objc/objc-static-method/TestObjCStaticMethod.py Fri Jul 8 15:48:47 2011 @@ -0,0 +1,68 @@ +"""Test calling functions in static methods.""" + +import os, time +import unittest2 +import lldb +import lldbutil +from lldbtest import * + +class TestObjCStaticMethod(TestBase): + + mydir = os.path.join("lang", "objc", "objc-static-method") + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test + def test_with_dsym_and_python_api(self): + """Test calling functions in static methods.""" + self.buildDsym() + self.objc_static_method() + + @python_api_test + def test_with_dwarf_and_python_api(self): + """Test calling functions in static methods.""" + self.buildDwarf() + self.objc_static_method() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line numbers to break inside main(). + self.main_source = "static.m" + self.break_line = line_number(self.main_source, '// Set breakpoint here.') + + def objc_static_method(self): + """Test calling functions in static methods.""" + exe = os.path.join(os.getcwd(), "a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + bpt = target.BreakpointCreateByLocation(self.main_source, self.break_line) + self.assertTrue(bpt, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple (None, None, os.getcwd()) + + self.assertTrue(process, PROCESS_IS_VALID) + + # The stop reason of the thread should be breakpoint. + thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt) + + # Make sure we stopped at the first breakpoint. + self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.") + self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.") + + # Now make sure we can call a function in the static method we've stopped in. + frame = thread_list[0].GetFrameAtIndex(0) + self.assertTrue (frame, "Got a valid frame 0 frame.") + + cmd_value = frame.EvaluateExpression ("(char *) sel_getName (_cmd)") + self.assertTrue (cmd_value.IsValid()) + sel_name = cmd_value.GetSummary() + self.assertTrue (sel_name == "doSomethingWithString:", "Got the right value for the selector as string.") + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Added: lldb/trunk/test/lang/objc/objc-static-method/static.m URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/objc/objc-static-method/static.m?rev=134736&view=auto ============================================================================== --- lldb/trunk/test/lang/objc/objc-static-method/static.m (added) +++ lldb/trunk/test/lang/objc/objc-static-method/static.m Fri Jul 8 15:48:47 2011 @@ -0,0 +1,20 @@ +#import + + at interface Foo : NSObject ++(void) doSomethingWithString: (NSString *) string; + + at end + + at implementation Foo ++(void) doSomethingWithString: (NSString *) string +{ + NSLog (@"String is: %@.", string); // Set breakpoint here. + +} + at end + +int main() +{ + [Foo doSomethingWithString: @"Some string I have in mind."]; + return 0; +} From gclayton at apple.com Fri Jul 8 16:46:14 2011 From: gclayton at apple.com (Greg Clayton) Date: Fri, 08 Jul 2011 21:46:14 -0000 Subject: [Lldb-commits] [lldb] r134745 - in /lldb/trunk: include/lldb/Core/ValueObject.h include/lldb/Core/ValueObjectList.h include/lldb/Symbol/Variable.h include/lldb/Symbol/VariableList.h source/Commands/CommandObjectTarget.cpp source/Core/ValueObjectList.cpp source/Symbol/Variable.cpp source/Symbol/VariableList.cpp Message-ID: <20110708214614.597152A6C12D@llvm.org> Author: gclayton Date: Fri Jul 8 16:46:14 2011 New Revision: 134745 URL: http://llvm.org/viewvc/llvm-project?rev=134745&view=rev Log: Added the ability to see global variables with a variable expression path so you can do things like: (lldb) target variable g_global.a (lldb) target variable *g_global.ptr (lldb) target variable g_global.ptr[1] Modified: lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Core/ValueObjectList.h lldb/trunk/include/lldb/Symbol/Variable.h lldb/trunk/include/lldb/Symbol/VariableList.h lldb/trunk/source/Commands/CommandObjectTarget.cpp lldb/trunk/source/Core/ValueObjectList.cpp lldb/trunk/source/Symbol/Variable.cpp lldb/trunk/source/Symbol/VariableList.cpp Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Fri Jul 8 16:46:14 2011 @@ -121,9 +121,9 @@ GetValueForExpressionPathOptions(bool dot = false, bool no_ivar = false, bool bitfield = true) : - m_check_dot_vs_arrow_syntax(dot), - m_no_fragile_ivar(no_ivar), - m_allow_bitfields_syntax(bitfield) + m_check_dot_vs_arrow_syntax(dot), + m_no_fragile_ivar(no_ivar), + m_allow_bitfields_syntax(bitfield) { } Modified: lldb/trunk/include/lldb/Core/ValueObjectList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectList.h?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObjectList.h (original) +++ lldb/trunk/include/lldb/Core/ValueObjectList.h Fri Jul 8 16:46:14 2011 @@ -59,6 +59,9 @@ lldb::ValueObjectSP GetValueObjectAtIndex (uint32_t idx); + lldb::ValueObjectSP + RemoveValueObjectAtIndex (uint32_t idx); + void SetValueObjectAtIndex (uint32_t idx, const lldb::ValueObjectSP &valobj_sp); Modified: lldb/trunk/include/lldb/Symbol/Variable.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Variable.h?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/Variable.h (original) +++ lldb/trunk/include/lldb/Symbol/Variable.h Fri Jul 8 16:46:14 2011 @@ -140,6 +140,19 @@ { m_loc_is_const_data = b; } + + typedef uint32_t (*GetVariableCallback) (void *baton, + const char *name, + VariableList &var_list); + + + static Error + GetValuesForVariableExpressionPath (const char *variable_expr_path, + ExecutionContextScope *scope, + GetVariableCallback callback, + void *baton, + VariableList &variable_list, + ValueObjectList &valobj_list); protected: ConstString m_name; // The basename of the variable (no namespaces) Modified: lldb/trunk/include/lldb/Symbol/VariableList.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/VariableList.h?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/VariableList.h (original) +++ lldb/trunk/include/lldb/Symbol/VariableList.h Fri Jul 8 16:46:14 2011 @@ -45,6 +45,9 @@ GetVariableAtIndex(uint32_t idx); lldb::VariableSP + RemoveVariableAtIndex (uint32_t idx); + + lldb::VariableSP FindVariable (const ConstString& name); uint32_t Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Fri Jul 8 16:46:14 2011 @@ -433,7 +433,82 @@ ~CommandObjectTargetVariable () { } + + void + DumpValueObject (Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp, const char *root_name) + { + if (m_option_variable.format != eFormatDefault) + valobj_sp->SetFormat (m_option_variable.format); + + switch (var_sp->GetScope()) + { + case eValueTypeVariableGlobal: + if (m_option_variable.show_scope) + s.PutCString("GLOBAL: "); + break; + + case eValueTypeVariableStatic: + if (m_option_variable.show_scope) + s.PutCString("STATIC: "); + break; + + case eValueTypeVariableArgument: + if (m_option_variable.show_scope) + s.PutCString(" ARG: "); + break; + + case eValueTypeVariableLocal: + if (m_option_variable.show_scope) + s.PutCString(" LOCAL: "); + break; + + default: + break; + } + + if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) + { + var_sp->GetDeclaration ().DumpStopContext (&s, false); + s.PutCString (": "); + } + + const Format format = m_option_variable.format; + if (format != eFormatDefault) + valobj_sp->SetFormat (format); + + ValueObject::DumpValueObject (s, + valobj_sp.get(), + root_name, + m_varobj_options.ptr_depth, + 0, + m_varobj_options.max_depth, + m_varobj_options.show_types, + m_varobj_options.show_location, + m_varobj_options.use_objc, + m_varobj_options.use_dynamic, + false, + m_varobj_options.flat_output); + + } + + + static uint32_t GetVariableCallback (void *baton, + const char *name, + VariableList &variable_list) + { + Target *target = static_cast(baton); + if (target) + { + return target->GetImages().FindGlobalVariables (ConstString(name), + true, + UINT32_MAX, + variable_list); + } + return 0; + } + + virtual bool Execute (Args& args, CommandReturnObject &result) { @@ -444,9 +519,13 @@ const size_t argc = args.GetArgumentCount(); if (argc > 0) { + Stream &s = result.GetOutputStream(); + for (size_t idx = 0; idx < argc; ++idx) { - VariableList global_var_list; + VariableList variable_list; + ValueObjectList valobj_list; + const char *arg = args.GetArgumentAtIndex(idx); uint32_t matches = 0; if (m_option_variable.use_regex) @@ -461,14 +540,22 @@ matches = exe_ctx.target->GetImages().FindGlobalVariables (regex, true, UINT32_MAX, - global_var_list); + variable_list); } else { - matches = exe_ctx.target->GetImages().FindGlobalVariables (ConstString(arg), - true, - UINT32_MAX, - global_var_list); + Error error (Variable::GetValuesForVariableExpressionPath (arg, + exe_ctx.target, + GetVariableCallback, + exe_ctx.target, + variable_list, + valobj_list)); + +// matches = exe_ctx.target->GetImages().FindGlobalVariables (ConstString(arg), +// true, +// UINT32_MAX, +// variable_list); + matches = variable_list.GetSize(); } if (matches == 0) @@ -479,68 +566,17 @@ } else { - Stream &s = result.GetOutputStream(); for (uint32_t global_idx=0; global_idxSetFormat (m_option_variable.format); - - switch (var_sp->GetScope()) - { - case eValueTypeVariableGlobal: - if (m_option_variable.show_scope) - s.PutCString("GLOBAL: "); - break; - - case eValueTypeVariableStatic: - if (m_option_variable.show_scope) - s.PutCString("STATIC: "); - break; - - case eValueTypeVariableArgument: - if (m_option_variable.show_scope) - s.PutCString(" ARG: "); - break; - - case eValueTypeVariableLocal: - if (m_option_variable.show_scope) - s.PutCString(" LOCAL: "); - break; - - default: - break; - } - - if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) - { - var_sp->GetDeclaration ().DumpStopContext (&s, false); - s.PutCString (": "); - } - - const Format format = m_option_variable.format; - if (format != eFormatDefault) - valobj_sp->SetFormat (format); - - ValueObject::DumpValueObject (s, - valobj_sp.get(), - var_sp->GetName().GetCString(), - m_varobj_options.ptr_depth, - 0, - m_varobj_options.max_depth, - m_varobj_options.show_types, - m_varobj_options.show_location, - m_varobj_options.use_objc, - m_varobj_options.use_dynamic, - false, - m_varobj_options.flat_output); - } + DumpValueObject (s, var_sp, valobj_sp, arg); } } } Modified: lldb/trunk/source/Core/ValueObjectList.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectList.cpp?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObjectList.cpp (original) +++ lldb/trunk/source/Core/ValueObjectList.cpp Fri Jul 8 16:46:14 2011 @@ -82,6 +82,18 @@ return valobj_sp; } +lldb::ValueObjectSP +ValueObjectList::RemoveValueObjectAtIndex (uint32_t idx) +{ + lldb::ValueObjectSP valobj_sp; + if (idx < m_value_objects.size()) + { + valobj_sp = m_value_objects[idx]; + m_value_objects.erase (m_value_objects.begin() + idx); + } + return valobj_sp; +} + void ValueObjectList::SetValueObjectAtIndex (uint32_t idx, const ValueObjectSP &valobj_sp) { Modified: lldb/trunk/source/Symbol/Variable.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Variable.cpp?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Variable.cpp (original) +++ lldb/trunk/source/Symbol/Variable.cpp Fri Jul 8 16:46:14 2011 @@ -11,10 +11,13 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/RegularExpression.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectVariable.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" @@ -229,3 +232,163 @@ return false; } +Error +Variable::GetValuesForVariableExpressionPath (const char *variable_expr_path, + ExecutionContextScope *scope, + GetVariableCallback callback, + void *baton, + VariableList &variable_list, + ValueObjectList &valobj_list) +{ + Error error; + if (variable_expr_path && callback) + { + switch (variable_expr_path[0]) + { + case '*': + { + error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, + scope, + callback, + baton, + variable_list, + valobj_list); + if (error.Success()) + { + for (uint32_t i=0; iDereference(tmp_error)); + if (tmp_error.Fail()) + { + variable_list.RemoveVariableAtIndex (i); + valobj_list.RemoveValueObjectAtIndex (i); + } + else + { + valobj_list.SetValueObjectAtIndex (i, valobj_sp); + ++i; + } + } + } + else + { + error.SetErrorString ("unknown error"); + } + return error; + } + break; + + case '&': + { + error = Variable::GetValuesForVariableExpressionPath (variable_expr_path + 1, + scope, + callback, + baton, + variable_list, + valobj_list); + if (error.Success()) + { + for (uint32_t i=0; iAddressOf(tmp_error)); + if (tmp_error.Fail()) + { + variable_list.RemoveVariableAtIndex (i); + valobj_list.RemoveValueObjectAtIndex (i); + } + else + { + valobj_list.SetValueObjectAtIndex (i, valobj_sp); + ++i; + } + } + } + else + { + error.SetErrorString ("unknown error"); + } + return error; + } + break; + + default: + { + RegularExpression regex ("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"); + if (regex.Execute(variable_expr_path, 1)) + { + std::string variable_name; + if (regex.GetMatchAtIndex(variable_expr_path, 1, variable_name)) + { + variable_list.Clear(); + if (callback (baton, variable_name.c_str(), variable_list)) + { + uint32_t i=0; + while (i < variable_list.GetSize()) + { + VariableSP var_sp (variable_list.GetVariableAtIndex (i)); + ValueObjectSP valobj_sp; + if (var_sp) + { + ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp)); + if (variable_valobj_sp) + { + variable_expr_path += variable_name.size(); + if (*variable_expr_path) + { + const char* first_unparsed = NULL; + ValueObject::ExpressionPathScanEndReason reason_to_stop; + ValueObject::ExpressionPathEndResultType final_value_type; + ValueObject::GetValueForExpressionPathOptions options; + ValueObject::ExpressionPathAftermath final_task_on_target; + + valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path, + &first_unparsed, + &reason_to_stop, + &final_value_type, + options, + &final_task_on_target); + if (!valobj_sp) + { + error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'", + variable_expr_path, + var_sp->GetName().GetCString()); + } + } + else + { + // Just the name of a variable with no extras + valobj_sp = variable_valobj_sp; + } + } + } + + if (!var_sp || !valobj_sp) + { + variable_list.RemoveVariableAtIndex (i); + } + else + { + valobj_list.Append(valobj_sp); + ++i; + } + } + + if (variable_list.GetSize() > 0) + { + error.Clear(); + return error; + } + } + } + } + error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path); + } + break; + } + } + error.SetErrorString ("unknown error"); + return error; +} + Modified: lldb/trunk/source/Symbol/VariableList.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/VariableList.cpp?rev=134745&r1=134744&r2=134745&view=diff ============================================================================== --- lldb/trunk/source/Symbol/VariableList.cpp (original) +++ lldb/trunk/source/Symbol/VariableList.cpp Fri Jul 8 16:46:14 2011 @@ -72,6 +72,18 @@ return var_sp; } +VariableSP +VariableList::RemoveVariableAtIndex(uint32_t idx) +{ + VariableSP var_sp; + if (idx < m_variables.size()) + { + var_sp = m_variables[idx]; + m_variables.erase (m_variables.begin() + idx); + } + return var_sp; +} + uint32_t VariableList::FindVariableIndex (const VariableSP &var_sp) { From johnny.chen at apple.com Fri Jul 8 18:02:33 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 08 Jul 2011 23:02:33 -0000 Subject: [Lldb-commits] [lldb] r134766 - in /lldb/trunk: include/lldb/API/SBEvent.h include/lldb/API/SBListener.h scripts/lldb.swig test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py test/python_api/event/TestEvents.py Message-ID: <20110708230233.D4E572A6C12C@llvm.org> Author: johnny Date: Fri Jul 8 18:02:33 2011 New Revision: 134766 URL: http://llvm.org/viewvc/llvm-project?rev=134766&view=rev Log: o TestEvents.py: Add a usage example of SBEvent APIs. o SBEvent.h and SBListener.h: Add method docstrings for SBEvent.h and SBListener.h, and example usage of SBEvent into the class docstring of SBEvent. o lldb.swig: Add typemap for SBEvent::SBEvent (uint32_t event, const char *cstr, uint32_t cstr_len) so that we can use, in Python, obj2 = lldb.SBEvent(0, "abc") to create an SBEvent. Modified: lldb/trunk/include/lldb/API/SBEvent.h lldb/trunk/include/lldb/API/SBListener.h lldb/trunk/scripts/lldb.swig lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py lldb/trunk/test/python_api/event/TestEvents.py Modified: lldb/trunk/include/lldb/API/SBEvent.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBEvent.h?rev=134766&r1=134765&r2=134766&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBEvent.h (original) +++ lldb/trunk/include/lldb/API/SBEvent.h Fri Jul 8 18:02:33 2011 @@ -20,18 +20,124 @@ class SBBroadcaster; +#ifdef SWIG +%feature("docstring", +"API clients can register to receive events. + +For example, check out the following output: + +Try wait for event... +Event description: 0x103d0bb70 Event: broadcaster = 0x1009c8410, type = 0x00000001, data = { process = 0x1009c8400 (pid = 21528), state = running} +Event data flavor: Process::ProcessEventData +Process state: running + +Try wait for event... +Event description: 0x103a700a0 Event: broadcaster = 0x1009c8410, type = 0x00000001, data = { process = 0x1009c8400 (pid = 21528), state = stopped} +Event data flavor: Process::ProcessEventData +Process state: stopped + +Try wait for event... +Event description: 0x103d0d4a0 Event: broadcaster = 0x1009c8410, type = 0x00000001, data = { process = 0x1009c8400 (pid = 21528), state = exited} +Event data flavor: Process::ProcessEventData +Process state: exited + +Try wait for event... +timeout occurred waiting for event... + +from test/python_api/event/TestEventspy: + + def do_listen_for_and_print_event(self): + '''Create a listener and use SBEvent API to print the events received.''' + exe = os.path.join(os.getcwd(), 'a.out') + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + # Get a handle on the process's broadcaster. + broadcaster = process.GetBroadcaster() + + # Create an empty event object. + event = lldb.SBEvent() + + # Create a listener object and register with the broadcaster. + listener = lldb.SBListener('my listener') + rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) + self.assertTrue(rc, 'AddListener successfully retruns') + + traceOn = self.TraceOn() + if traceOn: + lldbutil.print_stacktraces(process) + + # Create MyListeningThread class to wait for any kind of event. + import threading + class MyListeningThread(threading.Thread): + def run(self): + count = 0 + # Let's only try at most 4 times to retrieve any kind of event. + # After that, the thread exits. + while not count > 3: + if traceOn: + print 'Try wait for event...' + if listener.WaitForEventForBroadcasterWithType(5, + broadcaster, + lldb.SBProcess.eBroadcastBitStateChanged, + event): + if traceOn: + desc = lldbutil.get_description(event) + print 'Event description:', desc + print 'Event data flavor:', event.GetDataFlavor() + print 'Process state:', lldbutil.state_type_to_str(process.GetState()) + print + else: + if traceOn: + print 'timeout occurred waiting for event...' + count = count + 1 + return + + # Let's start the listening thread to retrieve the events. + my_thread = MyListeningThread() + my_thread.start() + + # Use Python API to continue the process. The listening thread should be + # able to receive the state changed events. + process.Continue() + + # Use Python API to kill the process. The listening thread should be + # able to receive the state changed event, too. + process.Kill() + + # Wait until the 'MyListeningThread' terminates. + my_thread.join() +" + ) SBEvent; +#endif class SBEvent { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: SBEvent(); + SBEvent (const lldb::SBEvent &rhs); + // Make an event that contains a C string. +#ifdef SWIG + %feature("autodoc", "__init__(self, int type, str data) -> SBEvent") SBEvent; +#endif SBEvent (uint32_t event, const char *cstr, uint32_t cstr_len); ~SBEvent(); - SBEvent (const lldb::SBEvent &rhs); - #ifndef SWIG const SBEvent & operator = (const lldb::SBEvent &rhs); Modified: lldb/trunk/include/lldb/API/SBListener.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBListener.h?rev=134766&r1=134765&r2=134766&view=diff ============================================================================== --- lldb/trunk/include/lldb/API/SBListener.h (original) +++ lldb/trunk/include/lldb/API/SBListener.h Fri Jul 8 18:02:33 2011 @@ -16,6 +16,9 @@ class SBListener { +#ifdef SWIG + %feature("autodoc", "1"); +#endif public: SBListener (); Modified: lldb/trunk/scripts/lldb.swig URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/lldb.swig?rev=134766&r1=134765&r2=134766&view=diff ============================================================================== --- lldb/trunk/scripts/lldb.swig (original) +++ lldb/trunk/scripts/lldb.swig Fri Jul 8 18:02:33 2011 @@ -102,7 +102,16 @@ // typemap for an outgoing buffer -// See also SBProcess::WriteMemory. +// See also SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len). +%typemap(in) (const char *cstr, uint32_t cstr_len) { + if (!PyString_Check($input)) { + PyErr_SetString(PyExc_ValueError, "Expecting a string"); + return NULL; + } + $1 = (char *) PyString_AsString($input); + $2 = PyString_Size($input); +} +// And SBProcess::WriteMemory. %typemap(in) (const void *buf, size_t size) { if (!PyString_Check($input)) { PyErr_SetString(PyExc_ValueError, "Expecting a string"); Modified: lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py?rev=134766&r1=134765&r2=134766&view=diff ============================================================================== --- lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py (original) +++ lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py Fri Jul 8 18:02:33 2011 @@ -118,6 +118,7 @@ @python_api_test def test_SBEvent(self): obj = lldb.SBEvent() + obj2 = lldb.SBEvent(0, "abc") if self.TraceOn(): print obj self.assertFalse(obj) Modified: lldb/trunk/test/python_api/event/TestEvents.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/event/TestEvents.py?rev=134766&r1=134765&r2=134766&view=diff ============================================================================== --- lldb/trunk/test/python_api/event/TestEvents.py (original) +++ lldb/trunk/test/python_api/event/TestEvents.py Fri Jul 8 18:02:33 2011 @@ -14,6 +14,19 @@ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") @python_api_test + def test_listen_for_and_print_event_with_dsym(self): + """Exercise SBEvent API.""" + self.buildDsym() + self.do_listen_for_and_print_event() + + @python_api_test + def test_listen_for_and_print_event_with_dwarf(self): + """Exercise SBEvent API.""" + self.buildDwarf() + self.do_listen_for_and_print_event() + + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin") + @python_api_test def test_wait_for_event_with_dsym(self): """Exercise SBListener.WaitForEvent() API.""" self.buildDsym() @@ -44,6 +57,78 @@ # Find the line number to of function 'c'. self.line = line_number('main.c', '// Find the line number of function "c" here.') + def do_listen_for_and_print_event(self): + """Create a listener and use SBEvent API to print the events received.""" + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint on main.c by name 'c'. + breakpoint = target.BreakpointCreateByName('c', 'a.out') + + # Now launch the process, and do not stop at the entry point. + process = target.LaunchSimple(None, None, os.getcwd()) + self.assertTrue(process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + # Get a handle on the process's broadcaster. + broadcaster = process.GetBroadcaster() + + # Create an empty event object. + event = lldb.SBEvent() + + # Create a listener object and register with the broadcaster. + listener = lldb.SBListener("my listener") + rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) + self.assertTrue(rc, "AddListener successfully retruns") + + traceOn = self.TraceOn() + if traceOn: + lldbutil.print_stacktraces(process) + + # Create MyListeningThread class to wait for any kind of event. + import threading + class MyListeningThread(threading.Thread): + def run(self): + count = 0 + # Let's only try at most 4 times to retrieve any kind of event. + # After that, the thread exits. + while not count > 3: + if traceOn: + print "Try wait for event..." + if listener.WaitForEventForBroadcasterWithType(5, + broadcaster, + lldb.SBProcess.eBroadcastBitStateChanged, + event): + if traceOn: + desc = lldbutil.get_description(event) + print "Event description:", desc + print "Event data flavor:", event.GetDataFlavor() + print "Process state:", lldbutil.state_type_to_str(process.GetState()) + print + else: + if traceOn: + print "timeout occurred waiting for event..." + count = count + 1 + return + + # Let's start the listening thread to retrieve the events. + my_thread = MyListeningThread() + my_thread.start() + + # Use Python API to continue the process. The listening thread should be + # able to receive the state changed events. + process.Continue() + + # Use Python API to kill the process. The listening thread should be + # able to receive the state changed event, too. + process.Kill() + + # Wait until the 'MyListeningThread' terminates. + my_thread.join() + def do_wait_for_event(self): """Get the listener associated with the debugger and exercise WaitForEvent API.""" exe = os.path.join(os.getcwd(), "a.out") @@ -84,6 +169,8 @@ while not count > 3: if listener.WaitForEvent(5, event): #print "Got a valid event:", event + #print "Event data flavor:", event.GetDataFlavor() + #print "Event type:", lldbutil.state_type_to_str(event.GetType()) return count = count + 1 print "Timeout: listener.WaitForEvent" From johnny.chen at apple.com Fri Jul 8 18:07:53 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 08 Jul 2011 23:07:53 -0000 Subject: [Lldb-commits] [lldb] r134769 - /lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py Message-ID: <20110708230753.A571A2A6C12C@llvm.org> Author: johnny Date: Fri Jul 8 18:07:53 2011 New Revision: 134769 URL: http://llvm.org/viewvc/llvm-project?rev=134769&view=rev Log: Add some comment. Modified: lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py Modified: lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py?rev=134769&r1=134768&r2=134769&view=diff ============================================================================== --- lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py (original) +++ lldb/trunk/test/python_api/default-constructor/TestDefaultConstructorForAPIObjects.py Fri Jul 8 18:07:53 2011 @@ -118,6 +118,7 @@ @python_api_test def test_SBEvent(self): obj = lldb.SBEvent() + # This is just to test that typemap, as defined in lldb.swig, works. obj2 = lldb.SBEvent(0, "abc") if self.TraceOn(): print obj From johnny.chen at apple.com Fri Jul 8 18:33:36 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 08 Jul 2011 23:33:36 -0000 Subject: [Lldb-commits] [lldb] r134771 - in /lldb/trunk/test/lang/c/global_variables: TestGlobalVariables.py a.c Message-ID: <20110708233336.94D022A6C12C@llvm.org> Author: johnny Date: Fri Jul 8 18:33:36 2011 New Revision: 134771 URL: http://llvm.org/viewvc/llvm-project?rev=134771&view=rev Log: Add test scenarios for 'target variable' command into TestGlobalVariables.py file. Modified: lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py lldb/trunk/test/lang/c/global_variables/a.c Modified: lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py?rev=134771&r1=134770&r2=134771&view=diff ============================================================================== --- lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py (original) +++ lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py Fri Jul 8 18:33:36 2011 @@ -59,6 +59,14 @@ # 'frame variable' should support address-of operator. self.runCmd("frame variable &g_file_global_int") + # Exercise the 'target variable' command to display globals in a.c file. + self.expect("target variable g_a", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['g_a', '123']) + self.expect("target variable g_marked_spot.x", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['g_marked_spot.x', '20']) + self.expect("target variable g_marked_spot.y", VARIABLES_DISPLAYED_CORRECTLY, + substrs = ['g_marked_spot.y', '21']) + if __name__ == '__main__': import atexit Modified: lldb/trunk/test/lang/c/global_variables/a.c URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/global_variables/a.c?rev=134771&r1=134770&r2=134771&view=diff ============================================================================== --- lldb/trunk/test/lang/c/global_variables/a.c (original) +++ lldb/trunk/test/lang/c/global_variables/a.c Fri Jul 8 18:33:36 2011 @@ -7,4 +7,9 @@ // //===----------------------------------------------------------------------===// int g_a = 123; +struct Point { + int x; + int y; +}; +struct Point g_marked_spot = { 20, 21 }; From johnny.chen at apple.com Fri Jul 8 18:38:39 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 08 Jul 2011 23:38:39 -0000 Subject: [Lldb-commits] [lldb] r134772 - /lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py Message-ID: <20110708233839.881C82A6C12C@llvm.org> Author: johnny Date: Fri Jul 8 18:38:39 2011 New Revision: 134772 URL: http://llvm.org/viewvc/llvm-project?rev=134772&view=rev Log: Add rdar://problem/9747668 info for "target variable g_marked_spot.y" command. Modified: lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py Modified: lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py?rev=134772&r1=134771&r2=134772&view=diff ============================================================================== --- lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py (original) +++ lldb/trunk/test/lang/c/global_variables/TestGlobalVariables.py Fri Jul 8 18:38:39 2011 @@ -64,6 +64,11 @@ substrs = ['g_a', '123']) self.expect("target variable g_marked_spot.x", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['g_marked_spot.x', '20']) + + # rdar://problem/9747668 + # runCmd: target variable g_marked_spot.y + # output: (int) g_marked_spot.y = self.expect("target variable g_marked_spot.y", VARIABLES_DISPLAYED_CORRECTLY, substrs = ['g_marked_spot.y', '21']) From johnny.chen at apple.com Fri Jul 8 18:57:20 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 08 Jul 2011 23:57:20 -0000 Subject: [Lldb-commits] [lldb] r134775 - /lldb/trunk/scripts/Python/modify-python-lldb.py Message-ID: <20110708235720.848CE2A6C12D@llvm.org> Author: johnny Date: Fri Jul 8 18:57:20 2011 New Revision: 134775 URL: http://llvm.org/viewvc/llvm-project?rev=134775&view=rev Log: Missed the char_to_str_xform on the docstrings for the module level function definitions. Modified: lldb/trunk/scripts/Python/modify-python-lldb.py Modified: lldb/trunk/scripts/Python/modify-python-lldb.py URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/modify-python-lldb.py?rev=134775&r1=134774&r2=134775&view=diff ============================================================================== --- lldb/trunk/scripts/Python/modify-python-lldb.py (original) +++ lldb/trunk/scripts/Python/modify-python-lldb.py Fri Jul 8 18:57:20 2011 @@ -52,7 +52,9 @@ # # The one-liner docstring also needs char_to_str transformation, btw. # -one_liner_docstring_pattern = re.compile('^ """.*"""$') +TWO_SPACES = ' ' * 2 +EIGHT_SPACES = ' ' * 8 +one_liner_docstring_pattern = re.compile('^(%s|%s)""".*"""$' % (TWO_SPACES, EIGHT_SPACES)) # # lldb_iter() should appear before our first SB* class definition. From gclayton at apple.com Fri Jul 8 19:41:34 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 09 Jul 2011 00:41:34 -0000 Subject: [Lldb-commits] [lldb] r134779 - in /lldb/trunk: include/lldb/Symbol/ObjectFile.h source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp source/Plugins/ObjectFile/ELF/ObjectFileELF.h source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Message-ID: <20110709004134.5CDED2A6C12C@llvm.org> Author: gclayton Date: Fri Jul 8 19:41:34 2011 New Revision: 134779 URL: http://llvm.org/viewvc/llvm-project?rev=134779&view=rev Log: Added the ability to get an abstract file type (executable, object file, shared library, etc) and strata (user/kernel) from an object file. This will help with plug-in and platform selection when given a new binary with the "target create " command. Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ObjectFile.h?rev=134779&r1=134778&r2=134779&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ObjectFile.h (original) +++ lldb/trunk/include/lldb/Symbol/ObjectFile.h Fri Jul 8 19:41:34 2011 @@ -56,6 +56,27 @@ friend class lldb_private::Module; public: + typedef enum + { + eTypeInvalid = 0, + eTypeCoreFile, /// A core file that has a checkpoint of a program's execution state + eTypeExecutable, /// A normal executable + eTypeDebugInfo, /// An object file that contains only debug information + eTypeDynamicLinker, /// The platform's dynamic linker executable + eTypeObjectFile, /// An intermediate object file + eTypeSharedLibrary, /// A shared library that can be used during execution + eTypeStubLibrary, /// A library that can be linked against but not used for execution + eTypeUnknown, + } Type; + + typedef enum + { + eStrataInvalid = 0, + eStrataUnknown, + eStrataUser, + eStrataKernel + } Strata; + //------------------------------------------------------------------ /// Construct with a parent module, offset, and header data. /// @@ -66,6 +87,8 @@ ObjectFile (Module* module, const FileSpec *file_spec_ptr, lldb::addr_t offset, lldb::addr_t length, lldb::DataBufferSP& headerDataSP) : ModuleChild (module), m_file (), // This file could be different from the original module's file + m_type (eTypeInvalid), + m_strata (eStrataInvalid), m_offset (offset), m_length (length), m_data (headerDataSP, lldb::endian::InlHostByteOrder(), 4), @@ -356,11 +379,64 @@ virtual lldb_private::Address GetEntryPointAddress () { return Address();} + //------------------------------------------------------------------ + /// The object file should be able to calculate its type by looking + /// at its file header and possibly the sections or other data in + /// the object file. The file type is used in the debugger to help + /// select the correct plug-ins for the job at hand, so this is + /// important to get right. If any eTypeXXX definitions do not match + /// up with the type of file you are loading, please feel free to + /// add a new enumeration value. + /// + /// @return + /// The calculated file type for the current object file. + //------------------------------------------------------------------ + virtual Type + CalculateType() = 0; + + //------------------------------------------------------------------ + /// The object file should be able to calculate the strata of the + /// object file. + /// + /// Many object files for platforms might be for either user space + /// debugging or for kernel debugging. If your object file subclass + /// can figure this out, it will help with debugger plug-in selection + /// when it comes time to debug. + /// + /// @return + /// The calculated object file strata for the current object + /// file. + //------------------------------------------------------------------ + virtual Strata + CalculateStrata() = 0; + + //------------------------------------------------------------------ + // Member Functions + //------------------------------------------------------------------ + Type + GetType () + { + if (m_type == eTypeInvalid) + m_type = CalculateType(); + return m_type; + } + + Strata + GetStrata () + { + if (m_strata == eStrataInvalid) + m_strata = CalculateStrata(); + return m_strata; + } + + protected: //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ FileSpec m_file; + Type m_type; + Strata m_strata; lldb::addr_t m_offset; ///< The offset in bytes into the file, or the address in memory lldb::addr_t m_length; ///< The length of this object file if it is known (can be zero if length is unknown or can't be determined). DataExtractor m_data; ///< The data for this object file so things can be parsed lazily. Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=134779&r1=134778&r2=134779&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Fri Jul 8 19:41:34 2011 @@ -1421,3 +1421,74 @@ return true; } +ObjectFile::Type +ObjectFileELF::CalculateType() +{ + switch (m_header.e_type) + { + case llvm::ELF::ET_NONE: + // 0 - No file type + return eTypeUnknown; + + case llvm::ELF::ET_REL: + // 1 - Relocatable file + return eTypeObjectFile; + + case llvm::ELF::ET_EXEC: + // 2 - Executable file + return eTypeExecutable; + + case llvm::ELF::ET_DYN: + // 3 - Shared object file + return eTypeSharedLibrary; + + case ET_CORE: + // 4 - Core file + return eTypeCoreFile; + + default: + break; + } + return eTypeUnknown; +} + +ObjectFile::Strata +ObjectFileELF::CalculateStrata() +{ + switch (m_header.e_type) + { + case llvm::ELF::ET_NONE: + // 0 - No file type + return eStrataUnknown; + + case llvm::ELF::ET_REL: + // 1 - Relocatable file + return eStrataUnknown; + + case llvm::ELF::ET_EXEC: + // 2 - Executable file + // TODO: is there any way to detect that an executable is a kernel + // related executable by inspecting the program headers, section + // headers, symbols, or any other flag bits??? + return eStrataUser; + + case llvm::ELF::ET_DYN: + // 3 - Shared object file + // TODO: is there any way to detect that an shared library is a kernel + // related executable by inspecting the program headers, section + // headers, symbols, or any other flag bits??? + return eStrataUnknown; + + case ET_CORE: + // 4 - Core file + // TODO: is there any way to detect that an core file is a kernel + // related executable by inspecting the program headers, section + // headers, symbols, or any other flag bits??? + return eStrataUnknown; + + default: + break; + } + return eStrataUnknown; +} + Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=134779&r1=134778&r2=134779&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Fri Jul 8 19:41:34 2011 @@ -104,6 +104,12 @@ virtual lldb_private::Address GetEntryPointAddress (); + + virtual ObjectFile::Type + CalculateType(); + + virtual ObjectFile::Strata + CalculateStrata(); private: ObjectFileELF(lldb_private::Module* module, Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=134779&r1=134778&r2=134779&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Fri Jul 8 19:41:34 2011 @@ -1672,6 +1672,90 @@ } +ObjectFile::Type +ObjectFileMachO::CalculateType() +{ + switch (m_header.filetype) + { + case HeaderFileTypeObject: // 0x1u MH_OBJECT + if (GetAddressByteSize () == 4) + { + // 32 bit kexts are just object files, but they do have a valid + // UUID load command. + UUID uuid; + if (GetUUID(&uuid)) + { + // this checking for the UUID load command is not enough + // we could eventually look for the symbol named + // "OSKextGetCurrentIdentifier" as this is required of kexts + if (m_strata == eStrataInvalid) + m_strata = eStrataKernel; + return eTypeSharedLibrary; + } + } + return eTypeObjectFile; + + case HeaderFileTypeExecutable: return eTypeExecutable; // 0x2u MH_EXECUTE + case HeaderFileTypeFixedVMShlib: return eTypeSharedLibrary; // 0x3u MH_FVMLIB + case HeaderFileTypeCore: return eTypeCoreFile; // 0x4u MH_CORE + case HeaderFileTypePreloadedExecutable: return eTypeSharedLibrary; // 0x5u MH_PRELOAD + case HeaderFileTypeDynamicShlib: return eTypeSharedLibrary; // 0x6u MH_DYLIB + case HeaderFileTypeDynamicLinkEditor: return eTypeDynamicLinker; // 0x7u MH_DYLINKER + case HeaderFileTypeBundle: return eTypeSharedLibrary; // 0x8u MH_BUNDLE + case HeaderFileTypeDynamicShlibStub: return eTypeStubLibrary; // 0x9u MH_DYLIB_STUB + case HeaderFileTypeDSYM: return eTypeDebugInfo; // 0xAu MH_DSYM + case HeaderFileTypeKextBundle: return eTypeSharedLibrary; // 0xBu MH_KEXT_BUNDLE + default: + break; + } + return eTypeUnknown; +} + +ObjectFile::Strata +ObjectFileMachO::CalculateStrata() +{ + switch (m_header.filetype) + { + case HeaderFileTypeObject: // 0x1u MH_OBJECT + { + // 32 bit kexts are just object files, but they do have a valid + // UUID load command. + UUID uuid; + if (GetUUID(&uuid)) + { + // this checking for the UUID load command is not enough + // we could eventually look for the symbol named + // "OSKextGetCurrentIdentifier" as this is required of kexts + if (m_type == eTypeInvalid) + m_type = eTypeSharedLibrary; + + return eStrataKernel; + } + } + return eStrataUnknown; + + case HeaderFileTypeExecutable: // 0x2u MH_EXECUTE + // Check for the MH_DYLDLINK bit in the flags + if (m_header.flags & HeaderFlagBitIsDynamicLinkObject) + return eStrataUser; + return eStrataKernel; + + case HeaderFileTypeFixedVMShlib: return eStrataUser; // 0x3u MH_FVMLIB + case HeaderFileTypeCore: return eStrataUnknown; // 0x4u MH_CORE + case HeaderFileTypePreloadedExecutable: return eStrataUser; // 0x5u MH_PRELOAD + case HeaderFileTypeDynamicShlib: return eStrataUser; // 0x6u MH_DYLIB + case HeaderFileTypeDynamicLinkEditor: return eStrataUser; // 0x7u MH_DYLINKER + case HeaderFileTypeBundle: return eStrataUser; // 0x8u MH_BUNDLE + case HeaderFileTypeDynamicShlibStub: return eStrataUser; // 0x9u MH_DYLIB_STUB + case HeaderFileTypeDSYM: return eStrataUnknown; // 0xAu MH_DSYM + case HeaderFileTypeKextBundle: return eStrataKernel; // 0xBu MH_KEXT_BUNDLE + default: + break; + } + return eStrataUnknown; +} + + bool ObjectFileMachO::GetArchitecture (ArchSpec &arch) { Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h?rev=134779&r1=134778&r2=134779&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h (original) +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h Fri Jul 8 19:41:34 2011 @@ -110,6 +110,12 @@ virtual lldb_private::Address GetEntryPointAddress (); + virtual ObjectFile::Type + CalculateType(); + + virtual ObjectFile::Strata + CalculateStrata(); + protected: mutable lldb_private::Mutex m_mutex; llvm::MachO::mach_header m_header; From jingham at apple.com Fri Jul 8 19:55:34 2011 From: jingham at apple.com (Jim Ingham) Date: Sat, 09 Jul 2011 00:55:34 -0000 Subject: [Lldb-commits] [lldb] r134780 - in /lldb/trunk/source: Commands/CommandObjectMemory.cpp Interpreter/CommandObject.cpp Target/ThreadPlanStepOverBreakpoint.cpp Message-ID: <20110709005534.B65E42A6C12C@llvm.org> Author: jingham Date: Fri Jul 8 19:55:34 2011 New Revision: 134780 URL: http://llvm.org/viewvc/llvm-project?rev=134780&view=rev Log: Allow reading memory from files before the target has been run. Modified: lldb/trunk/source/Commands/CommandObjectMemory.cpp lldb/trunk/source/Interpreter/CommandObject.cpp lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp Modified: lldb/trunk/source/Commands/CommandObjectMemory.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectMemory.cpp?rev=134780&r1=134779&r2=134780&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectMemory.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectMemory.cpp Fri Jul 8 19:55:34 2011 @@ -298,7 +298,7 @@ "memory read", "Read from the memory of the process being debugged.", NULL, - eFlagProcessMustBeLaunched), + eFlagProcessMustBePaused), m_option_group (interpreter), m_format_options (eFormatBytesWithASCII, 0, true), m_memory_options (), @@ -351,9 +351,9 @@ CommandReturnObject &result) { ExecutionContext exe_ctx (m_interpreter.GetExecutionContext()); - if (exe_ctx.process == NULL) + if (exe_ctx.target == NULL) { - result.AppendError("need a process to read memory"); + result.AppendError("need at least a target to read memory"); result.SetStatus(eReturnStatusFailed); return false; } @@ -561,7 +561,8 @@ if (!clang_ast_type.GetOpaqueQualType()) { data_sp.reset (new DataBufferHeap (total_byte_size, '\0')); - bytes_read = exe_ctx.process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error); + Address address(NULL, addr); + bytes_read = exe_ctx.target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error); if (bytes_read == 0) { result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr); Modified: lldb/trunk/source/Interpreter/CommandObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObject.cpp?rev=134780&r1=134779&r2=134780&view=diff ============================================================================== --- lldb/trunk/source/Interpreter/CommandObject.cpp (original) +++ lldb/trunk/source/Interpreter/CommandObject.cpp Fri Jul 8 19:55:34 2011 @@ -229,9 +229,13 @@ Process *process = m_interpreter.GetExecutionContext().process; if (process == NULL) { - result.AppendError ("Process must exist."); - result.SetStatus (eReturnStatusFailed); - return false; + // A process that is not running is considered paused. + if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched)) + { + result.AppendError ("Process must exist."); + result.SetStatus (eReturnStatusFailed); + return false; + } } else { Modified: lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp?rev=134780&r1=134779&r2=134780&view=diff ============================================================================== --- lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp (original) +++ lldb/trunk/source/Target/ThreadPlanStepOverBreakpoint.cpp Fri Jul 8 19:55:34 2011 @@ -39,7 +39,6 @@ { m_breakpoint_addr = m_thread.GetRegisterContext()->GetPC(); m_breakpoint_site_id = m_thread.GetProcess().GetBreakpointSiteList().FindIDByAddress (m_breakpoint_addr); - } ThreadPlanStepOverBreakpoint::~ThreadPlanStepOverBreakpoint () From vasil.georgiev.vasilev at cern.ch Sat Jul 9 06:20:08 2011 From: vasil.georgiev.vasilev at cern.ch (Vassil Vassilev) Date: Sat, 9 Jul 2011 13:20:08 +0200 Subject: [Lldb-commits] Hi All! In-Reply-To: <20110629235000.GA21133@pcc.me.uk> References: <4DF22EFC.3040307@cern.ch> <20110629235000.GA21133@pcc.me.uk> Message-ID: <4E183968.4000000@cern.ch> Hi Peter, Sorry for the delayed answer I didn't have much time. I spent a great deal of time on cling's error recovery. You are right make doxygen is much easier than setting flags just to get the doxygen.cfg. I am attaching the new patches. Please let me know if I misunderstood something or something needs to be fixed. Cheers, Vassil On 06/30/2011 01:50 AM, Peter Collingbourne wrote: > Hi Vassil, > > On Fri, Jun 10, 2011 at 04:49:32PM +0200, Vassil Vassilev wrote: >> Hi, >> Can I say Hi to lldb community with the attached patch. >> I saw that lldb didn't have doxygen documentation on the website and >> decided to see what I could do. Recently I did that for cling so I've >> made few changes to adapt it for lldb. It is customization of clang's >> approach of generating documentation. Be careful it's slow and space >> consuming ;) > Thanks for the patch. > > I don't think we can accept it yet, because it will only work for a > website-style build (i.e. if BUILD_FOR_WEBSITE is set) because there > is no way to build the doxygen.cfg otherwise. Ideally we would like > "make doxygen" in the docs directory to work for a standard build. > For LLVM and clang this is done by having LLVM's configure script > run an AC_CONFIG_FILES pass over the doxygen.cfg.in file (yes, this > isn't ideal for a large number of projects, but I don't think we're > at that point yet). You can see the necessary changes I made in > clang r131282 and LLVM r131279. > > Thanks, -------------- next part -------------- A non-text attachment was scrubbed... Name: lldb-doxygen-enabled.diff Type: text/x-patch Size: 90995 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/lldb-commits/attachments/20110709/da66608a/attachment-0002.bin -------------- next part -------------- A non-text attachment was scrubbed... Name: llvm-autoconf-lldb.diff Type: text/x-patch Size: 1503 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/lldb-commits/attachments/20110709/da66608a/attachment-0003.bin From gclayton at apple.com Sat Jul 9 12:12:27 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 09 Jul 2011 17:12:27 -0000 Subject: [Lldb-commits] [lldb] r134823 - /lldb/trunk/source/Symbol/ClangASTContext.cpp Message-ID: <20110709171227.682222A6C12C@llvm.org> Author: gclayton Date: Sat Jul 9 12:12:27 2011 New Revision: 134823 URL: http://llvm.org/viewvc/llvm-project?rev=134823&view=rev Log: Fixed an issue with getting the size of an array from an opaque clang_type_t variable where we were using a static cast when we shouldn't have been. Fixed another array related issue where we weren't looking through a typedef. Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=134823&r1=134822&r2=134823&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Sat Jul 9 12:12:27 2011 @@ -4624,9 +4624,21 @@ { if (clang_type) { - const ConstantArrayType *array = cast(QualType::getFromOpaquePtr(clang_type).getTypePtr()); - if (array) - return array->getSize().getLimitedValue(); + QualType qual_type(QualType::getFromOpaquePtr(clang_type)); + const clang::Type::TypeClass type_class = qual_type->getTypeClass(); + switch (type_class) + { + case clang::Type::ConstantArray: + { + const ConstantArrayType *array = cast(QualType::getFromOpaquePtr(clang_type).getTypePtr()); + if (array) + return array->getSize().getLimitedValue(); + } + break; + + case clang::Type::Typedef: + return ClangASTContext::GetArraySize(cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); + } } return 0; } @@ -4644,30 +4656,39 @@ { default: break; + case clang::Type::ConstantArray: if (member_type) *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = cast(qual_type)->getSize().getLimitedValue(ULLONG_MAX); return true; + case clang::Type::IncompleteArray: if (member_type) *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = 0; return true; + case clang::Type::VariableArray: if (member_type) *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = 0; return true; + case clang::Type::DependentSizedArray: if (member_type) *member_type = cast(qual_type)->getElementType().getAsOpaquePtr(); if (size) *size = 0; return true; + + case clang::Type::Typedef: + return ClangASTContext::IsArrayType (cast(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), + member_type, + size); } return false; } From gclayton at apple.com Sat Jul 9 12:14:57 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 09 Jul 2011 17:14:57 -0000 Subject: [Lldb-commits] [lldb] r134824 - /lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Message-ID: <20110709171457.748BC2A6C12C@llvm.org> Author: gclayton Date: Sat Jul 9 12:14:57 2011 New Revision: 134824 URL: http://llvm.org/viewvc/llvm-project?rev=134824&view=rev Log: Fixed an issue where we weren't zeroing out the type fully thanks to a nice clang warning! Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp?rev=134824&r1=134823&r2=134824&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp Sat Jul 9 12:14:57 2011 @@ -971,7 +971,7 @@ if (bytes_read == sizeof(llvm::MachO::mach_header)) { uint32_t offset = 0; - ::memset (header, 0, sizeof(header)); + ::memset (header, 0, sizeof(llvm::MachO::mach_header)); // Get the magic byte unswapped so we can figure out what we are dealing with DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4); From gclayton at apple.com Sat Jul 9 12:15:55 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 09 Jul 2011 17:15:55 -0000 Subject: [Lldb-commits] [lldb] r134825 - in /lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel: DynamicLoaderMacOSXKernel.cpp DynamicLoaderMacOSXKernel.h Message-ID: <20110709171556.006182A6C12C@llvm.org> Author: gclayton Date: Sat Jul 9 12:15:55 2011 New Revision: 134825 URL: http://llvm.org/viewvc/llvm-project?rev=134825&view=rev Log: More cleanup on the this plug-in and tried to set the notification breakpoint. I haven't been able to see this breakpoint get hit yet so I still have testing I need to do with the kernel dynamic loader. Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp?rev=134825&r1=134824&r2=134825&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.cpp Sat Jul 9 12:15:55 2011 @@ -89,12 +89,9 @@ m_kernel(), m_kext_summary_header_addr (), m_kext_summary_header (), - m_kext_summary_header_stop_id (0), m_break_id (LLDB_INVALID_BREAK_ID), m_kext_summaries(), - m_kext_summaries_stop_id (UINT32_MAX), - m_mutex(Mutex::eMutexTypeRecursive), - m_notification_callbacks () + m_mutex(Mutex::eMutexTypeRecursive) { } @@ -106,6 +103,12 @@ Clear(true); } +void +DynamicLoaderMacOSXKernel::UpdateIfNeeded() +{ + LoadKernelModuleIfNeeded(); + SetNotificationBreakpointIfNeeded (); +} //------------------------------------------------------------------ /// Called after attaching a process. /// @@ -116,8 +119,7 @@ DynamicLoaderMacOSXKernel::DidAttach () { PrivateInitialize(m_process); - LoadKernelModule(); - SetNotificationBreakpoint (); + UpdateIfNeeded(); } //------------------------------------------------------------------ @@ -130,8 +132,7 @@ DynamicLoaderMacOSXKernel::DidLaunch () { PrivateInitialize(m_process); - LoadKernelModule(); - SetNotificationBreakpoint (); + UpdateIfNeeded(); } @@ -151,18 +152,9 @@ m_kernel.Clear(false); m_kext_summary_header_addr.Clear(); m_kext_summaries.clear(); - m_kext_summaries_stop_id = 0; m_break_id = LLDB_INVALID_BREAK_ID; } -//---------------------------------------------------------------------- -// Check if we have found DYLD yet -//---------------------------------------------------------------------- -bool -DynamicLoaderMacOSXKernel::DidSetNotificationBreakpoint() const -{ - return LLDB_BREAK_ID_IS_VALID (m_break_id); -} //---------------------------------------------------------------------- // Load the kernel module and initialize the "m_kernel" member. Return @@ -170,8 +162,8 @@ // calls to this function should return false after the kernel has been // already loaded). //---------------------------------------------------------------------- -bool -DynamicLoaderMacOSXKernel::LoadKernelModule() +void +DynamicLoaderMacOSXKernel::LoadKernelModuleIfNeeded() { if (!m_kext_summary_header_addr.IsValid()) { @@ -201,19 +193,16 @@ UpdateImageLoadAddress (m_kernel); // Update all image infos - ReadAllKextSummaries (false); - return true; + ReadAllKextSummaries (); } } else { m_kernel.Clear(false); } - return false; } } } - return false; } bool @@ -393,25 +382,30 @@ // or not (based on global preference). //---------------------------------------------------------------------- bool -DynamicLoaderMacOSXKernel::NotifyBreakpointHit (void *baton, - StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id) +DynamicLoaderMacOSXKernel::BreakpointHitCallback (void *baton, + StoppointCallbackContext *context, + user_id_t break_id, + user_id_t break_loc_id) { - DynamicLoaderMacOSXKernel* dyld_instance = (DynamicLoaderMacOSXKernel*) baton; - - // Return true to stop the target, false to just let the target run - return dyld_instance->GetStopWhenImagesChange(); + return static_cast(baton)->BreakpointHit (context, break_id, break_loc_id); } bool +DynamicLoaderMacOSXKernel::BreakpointHit (StoppointCallbackContext *context, + user_id_t break_id, + user_id_t break_loc_id) +{ + ReadAllKextSummaries (); + return GetStopWhenImagesChange(); +} + + +bool DynamicLoaderMacOSXKernel::ReadKextSummaryHeader () { Mutex::Locker locker(m_mutex); // the all image infos is already valid for this process stop ID - if (m_process->GetStopID() == m_kext_summaries_stop_id) - return true; m_kext_summaries.clear(); if (m_kext_summary_header_addr.IsValid()) @@ -433,7 +427,6 @@ m_kext_summary_header.entry_size = data.GetU32(&offset); m_kext_summary_header.entry_count = data.GetU32(&offset); m_kext_summary_header.reserved = data.GetU32(&offset); - m_kext_summary_header_stop_id = m_process->GetStopID(); return true; } } @@ -442,17 +435,15 @@ bool -DynamicLoaderMacOSXKernel::ParseKextSummaries (const lldb_private::Address &kext_summary_addr, +DynamicLoaderMacOSXKernel::ParseKextSummaries (const Address &kext_summary_addr, uint32_t count) { OSKextLoadedKextSummary::collection kext_summaries; - LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf ("Adding %d modules.\n"); Mutex::Locker locker(m_mutex); - if (m_process->GetStopID() == m_kext_summaries_stop_id) - return true; if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries)) return false; @@ -469,7 +460,6 @@ } } bool return_value = AddModulesUsingImageInfos (kext_summaries); - m_kext_summaries_stop_id = m_process->GetStopID(); return return_value; } @@ -481,7 +471,7 @@ { // Now add these images to the main list. ModuleList loaded_module_list; - LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); for (uint32_t idx = 0; idx < image_infos.size(); ++idx) { @@ -536,7 +526,7 @@ uint32_t -DynamicLoaderMacOSXKernel::ReadKextSummaries (const lldb_private::Address &kext_summary_addr, +DynamicLoaderMacOSXKernel::ReadKextSummaries (const Address &kext_summary_addr, uint32_t image_infos_count, OSKextLoadedKextSummary::collection &image_infos) { @@ -585,26 +575,20 @@ } bool -DynamicLoaderMacOSXKernel::ReadAllKextSummaries (bool force) +DynamicLoaderMacOSXKernel::ReadAllKextSummaries () { - LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + LogSP log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); Mutex::Locker locker(m_mutex); - if (!force) - { - if (m_process->GetStopID() == m_kext_summaries_stop_id || m_kext_summaries.size() != 0) - return false; - } - + if (ReadKextSummaryHeader ()) { - if (m_kext_summary_header.entry_count > 0) + if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid()) { Address summary_addr (m_kext_summary_header_addr); summary_addr.Slide(16); if (!ParseKextSummaries (summary_addr, m_kext_summary_header.entry_count)) { - DEBUG_PRINTF( "unable to read all data for all_dylib_infos."); m_kext_summaries.clear(); } return true; @@ -636,7 +620,7 @@ ::memset (&kext_summary.header, 0, sizeof(kext_summary.header)); // Get the magic byte unswapped so we can figure out what we are dealing with - DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), lldb::endian::InlHostByteOrder(), 4); + DataExtractor data(header_bytes.GetBytes(), header_bytes.GetByteSize(), endian::InlHostByteOrder(), 4); kext_summary.header.magic = data.GetU32(&offset); Address load_cmd_addr = kext_summary.so_address; data.SetByteOrder(DynamicLoaderMacOSXKernel::GetByteOrderFromMagic(kext_summary.header.magic)); @@ -791,7 +775,7 @@ // Dump a Segment to the file handle provided. //---------------------------------------------------------------------- void -DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, lldb::addr_t slide) const +DynamicLoaderMacOSXKernel::Segment::PutToLog (Log *log, addr_t slide) const { if (log) { @@ -831,18 +815,6 @@ if (log == NULL) return; uint8_t *u = (uint8_t *)uuid.GetBytes(); -// -// char name[KERNEL_MODULE_MAX_NAME]; -// lldb::ModuleSP module_sp; -// lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros -// uint64_t address; -// uint64_t size; -// uint64_t version; -// uint32_t load_tag; -// uint32_t flags; -// uint64_t reference_list; -// llvm::MachO::mach_header header; // The mach header for this image -// std::vector segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) if (address == LLDB_INVALID_ADDRESS) { @@ -916,32 +888,22 @@ m_process->GetTarget().GetSectionLoadList().Clear(); } -bool -DynamicLoaderMacOSXKernel::SetNotificationBreakpoint () +void +DynamicLoaderMacOSXKernel::SetNotificationBreakpointIfNeeded () { - // TODO: Add breakpoint to detected dynamic kext loads/unloads. We aren't - // doing any live dynamic checks for kernel kexts being loaded or unloaded - // on the fly yet. -// DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); -// if (m_break_id == LLDB_INVALID_BREAK_ID) -// { -// if (m_kext_summaries.notification != LLDB_INVALID_ADDRESS) -// { -// Address so_addr; -// // Set the notification breakpoint and install a breakpoint -// // callback function that will get called each time the -// // breakpoint gets hit. We will use this to track when shared -// // libraries get loaded/unloaded. -// -// if (m_process->GetTarget().GetSectionLoadList().ResolveLoadAddress(m_kext_summaries.notification, so_addr)) -// { -// Breakpoint *dyld_break = m_process->GetTarget().CreateBreakpoint (so_addr, true).get(); -// dyld_break->SetCallback (DynamicLoaderMacOSXKernel::NotifyBreakpointHit, this, true); -// m_break_id = dyld_break->GetID(); -// } -// } -// } - return m_break_id != LLDB_INVALID_BREAK_ID; + if (m_break_id == LLDB_INVALID_BREAK_ID) + { + DEBUG_PRINTF("DynamicLoaderMacOSXKernel::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); + + const bool internal_bp = false; + Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&m_kernel.module_sp->GetFileSpec(), + "OSKextLoadedKextSummariesUpdated", + eFunctionNameTypeFull, + internal_bp).get(); + + bp->SetCallback (DynamicLoaderMacOSXKernel::BreakpointHitCallback, this, true); + m_break_id = bp->GetID(); + } } //---------------------------------------------------------------------- @@ -964,16 +926,7 @@ break; case eStateStopped: - // Keep trying find dyld and set our notification breakpoint each time - // we stop until we succeed - if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) - { - if (LoadKernelModule()) - { - } - - SetNotificationBreakpoint (); - } + UpdateIfNeeded(); break; case eStateRunning: @@ -991,79 +944,9 @@ DynamicLoaderMacOSXKernel::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) { ThreadPlanSP thread_plan_sp; - StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); - const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); - Symbol *current_symbol = current_context.symbol; - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - - if (current_symbol != NULL) - { - if (current_symbol->IsTrampoline()) - { - const ConstString &trampoline_name = current_symbol->GetMangled().GetName(Mangled::ePreferMangled); - - if (trampoline_name) - { - SymbolContextList target_symbols; - ModuleList &images = thread.GetProcess().GetTarget().GetImages(); - images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, target_symbols); - // FIXME - Make the Run to Address take multiple addresses, and - // run to any of them. - uint32_t num_symbols = target_symbols.GetSize(); - if (num_symbols == 1) - { - SymbolContext context; - AddressRange addr_range; - if (target_symbols.GetContextAtIndex(0, context)) - { - context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); - thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addr_range.GetBaseAddress(), stop_others)); - } - else - { - if (log) - log->Printf ("Couldn't resolve the symbol context."); - } - } - else if (num_symbols > 1) - { - std::vector addresses; - addresses.resize (num_symbols); - for (uint32_t i = 0; i < num_symbols; i++) - { - SymbolContext context; - AddressRange addr_range; - if (target_symbols.GetContextAtIndex(i, context)) - { - context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); - lldb::addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(&thread.GetProcess().GetTarget()); - addresses[i] = load_addr; - } - } - if (addresses.size() > 0) - thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, addresses, stop_others)); - else - { - if (log) - log->Printf ("Couldn't resolve the symbol contexts."); - } - } - else - { - if (log) - { - log->Printf ("Could not find symbol for trampoline target: \"%s\"", trampoline_name.AsCString()); - } - } - } - } - } - else - { - if (log) - log->Printf ("Could not find symbol for step through."); - } - + LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + if (log) + log->Printf ("Could not find symbol for step through."); return thread_plan_sp; } Modified: lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h?rev=134825&r1=134824&r2=134825&view=diff ============================================================================== --- lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h (original) +++ lldb/trunk/source/Plugins/DynamicLoader/MacOSX-Kernel/DynamicLoaderMacOSXKernel.h Sat Jul 9 12:15:55 2011 @@ -89,11 +89,12 @@ void PrivateProcessStateChanged (lldb_private::Process *process, lldb::StateType state); - bool - LoadKernelModule (); + + void + UpdateIfNeeded(); - bool - DidSetNotificationBreakpoint () const; + void + LoadKernelModuleIfNeeded (); void Clear (bool clear_process); @@ -102,11 +103,15 @@ PutToLog (lldb_private::Log *log) const; static bool - NotifyBreakpointHit (void *baton, - lldb_private::StoppointCallbackContext *context, - lldb::user_id_t break_id, - lldb::user_id_t break_loc_id); + BreakpointHitCallback (void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + bool + BreakpointHit (lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); uint32_t AddrByteSize() { @@ -373,11 +378,11 @@ bool can_create, bool *did_create_ptr); - bool - SetNotificationBreakpoint (); + void + SetNotificationBreakpointIfNeeded (); bool - ReadAllKextSummaries (bool force); + ReadAllKextSummaries (); bool ReadKextSummaryHeader (); @@ -408,12 +413,9 @@ OSKextLoadedKextSummary m_kernel; // Info about the current kernel image being used lldb_private::Address m_kext_summary_header_addr; OSKextLoadedKextSummaryHeader m_kext_summary_header; - uint32_t m_kext_summary_header_stop_id; // The process stop ID that "m_kext_summary_header" is valid for - lldb::user_id_t m_break_id; OSKextLoadedKextSummary::collection m_kext_summaries; - uint32_t m_kext_summaries_stop_id; // The process stop ID that "m_kext_summaries" is valid for mutable lldb_private::Mutex m_mutex; - lldb_private::Process::Notifications m_notification_callbacks; + lldb::user_id_t m_break_id; private: DISALLOW_COPY_AND_ASSIGN (DynamicLoaderMacOSXKernel); From gclayton at apple.com Sat Jul 9 12:16:43 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 09 Jul 2011 17:16:43 -0000 Subject: [Lldb-commits] [lldb] r134826 - in /lldb/trunk: include/lldb/Target/Target.h source/Target/Target.cpp Message-ID: <20110709171643.7640E2A6C12C@llvm.org> Author: gclayton Date: Sat Jul 9 12:16:43 2011 New Revision: 134826 URL: http://llvm.org/viewvc/llvm-project?rev=134826&view=rev Log: Fixed some const issues with args to some lldb_private::Target functions. Modified: lldb/trunk/include/lldb/Target/Target.h lldb/trunk/source/Target/Target.cpp Modified: lldb/trunk/include/lldb/Target/Target.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=134826&r1=134825&r2=134826&view=diff ============================================================================== --- lldb/trunk/include/lldb/Target/Target.h (original) +++ lldb/trunk/include/lldb/Target/Target.h Sat Jul 9 12:16:43 2011 @@ -239,13 +239,13 @@ // Use this to create a function breakpoint by regexp in containingModule, or all modules if it is NULL lldb::BreakpointSP - CreateBreakpoint (FileSpec *containingModule, + CreateBreakpoint (const FileSpec *containingModule, RegularExpression &func_regexp, bool internal = false); // Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL lldb::BreakpointSP - CreateBreakpoint (FileSpec *containingModule, + CreateBreakpoint (const FileSpec *containingModule, const char *func_name, uint32_t func_name_type_mask, bool internal = false); Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=134826&r1=134825&r2=134826&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Sat Jul 9 12:16:43 2011 @@ -213,7 +213,7 @@ } BreakpointSP -Target::CreateBreakpoint (FileSpec *containingModule, const char *func_name, uint32_t func_name_type_mask, bool internal) +Target::CreateBreakpoint (const FileSpec *containingModule, const char *func_name, uint32_t func_name_type_mask, bool internal) { BreakpointSP bp_sp; if (func_name) @@ -247,7 +247,7 @@ } BreakpointSP -Target::CreateBreakpoint (FileSpec *containingModule, RegularExpression &func_regex, bool internal) +Target::CreateBreakpoint (const FileSpec *containingModule, RegularExpression &func_regex, bool internal) { SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule)); BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex)); From gclayton at apple.com Sat Jul 9 12:17:07 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 09 Jul 2011 17:17:07 -0000 Subject: [Lldb-commits] [lldb] r134827 - /lldb/trunk/source/Core/ValueObject.cpp Message-ID: <20110709171707.A97902A6C12C@llvm.org> Author: gclayton Date: Sat Jul 9 12:17:07 2011 New Revision: 134827 URL: http://llvm.org/viewvc/llvm-project?rev=134827&view=rev Log: Limit the character array summary to 512 bytes. Modified: lldb/trunk/source/Core/ValueObject.cpp Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134827&r1=134826&r2=134827&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Sat Jul 9 12:17:07 2011 @@ -567,10 +567,20 @@ AddressType cstr_address_type = eAddressTypeInvalid; size_t cstr_len = 0; + bool capped_data = false; if (type_flags.Test (ClangASTContext::eTypeIsArray)) { // We have an array cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > 512) // TODO: make cap a setting + { + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > 512) // TODO: make cap a setting + { + capped_data = true; + cstr_len = 512; + } + } cstr_address = GetAddressOf (cstr_address_type, true); } else @@ -601,6 +611,8 @@ LLDB_INVALID_ADDRESS,// base address 0, // bitfield bit size 0); // bitfield bit offset + if (capped_data) + sstr << "..."; sstr << '"'; } } From gclayton at apple.com Sat Jul 9 15:12:33 2011 From: gclayton at apple.com (Greg Clayton) Date: Sat, 09 Jul 2011 20:12:33 -0000 Subject: [Lldb-commits] [lldb] r134846 - in /lldb/trunk: include/lldb/Core/ValueObject.h include/lldb/Symbol/ClangASTContext.h source/API/SBType.cpp source/Commands/CommandObjectTarget.cpp source/Core/ValueObject.cpp source/Symbol/ClangASTContext.cpp source/Symbol/Variable.cpp Message-ID: <20110709201233.910CE2A6C12C@llvm.org> Author: gclayton Date: Sat Jul 9 15:12:33 2011 New Revision: 134846 URL: http://llvm.org/viewvc/llvm-project?rev=134846&view=rev Log: Fixed the global and static variables to always be in scope. Made it so that you can create synthetic children of array value objects. This is for creating array members when the array index is out of range. This comes in handy when you have a structure definition like: struct Collection { uint32_t count; Item array[0]; }; "array" has 1 item, but many times in practice there are more items in "item_array". This allows you to do: (lldb) target variable g_collection.array[3] To implement this, the get child at index has been modified to have a "ignore_array_bounds" boolean that can be set to true. Modified: lldb/trunk/include/lldb/Core/ValueObject.h lldb/trunk/include/lldb/Symbol/ClangASTContext.h lldb/trunk/source/API/SBType.cpp lldb/trunk/source/Commands/CommandObjectTarget.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Symbol/ClangASTContext.cpp lldb/trunk/source/Symbol/Variable.cpp Modified: lldb/trunk/include/lldb/Core/ValueObject.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=134846&r1=134845&r2=134846&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/ValueObject.h (original) +++ lldb/trunk/include/lldb/Core/ValueObject.h Sat Jul 9 15:12:33 2011 @@ -349,6 +349,9 @@ IsPointerType (); virtual bool + IsArrayType (); + + virtual bool IsScalarType (); virtual bool @@ -524,6 +527,9 @@ GetSyntheticArrayMemberFromPointer (int32_t index, bool can_create); lldb::ValueObjectSP + GetSyntheticArrayMemberFromArray (int32_t index, bool can_create); + + lldb::ValueObjectSP GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create); lldb::ValueObjectSP Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=134846&r1=134845&r2=134846&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original) +++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Sat Jul 9 15:12:33 2011 @@ -415,6 +415,7 @@ uint32_t idx, bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string& child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, @@ -431,6 +432,7 @@ uint32_t idx, bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string& child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, Modified: lldb/trunk/source/API/SBType.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBType.cpp?rev=134846&r1=134845&r2=134846&view=diff ============================================================================== --- lldb/trunk/source/API/SBType.cpp (original) +++ lldb/trunk/source/API/SBType.cpp Sat Jul 9 15:12:33 2011 @@ -107,6 +107,7 @@ SBType::GetChildAtIndex (bool omit_empty_base_classes, uint32_t idx, SBTypeMember &member) { void *child_clang_type = NULL; + bool ignore_array_bounds = false; std::string child_name; uint32_t child_byte_size = 0; int32_t child_byte_offset = 0; @@ -125,6 +126,7 @@ idx, false, // transparent pointers omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=134846&r1=134845&r2=134846&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Sat Jul 9 15:12:33 2011 @@ -545,7 +545,7 @@ else { Error error (Variable::GetValuesForVariableExpressionPath (arg, - exe_ctx.target, + exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, exe_ctx.target, variable_list, Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134846&r1=134845&r2=134846&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Sat Jul 9 15:12:33 2011 @@ -430,7 +430,7 @@ ValueObject *valobj = NULL; bool omit_empty_base_classes = true; - + bool ignore_array_bounds = synthetic_array_member; std::string child_name_str; uint32_t child_byte_size = 0; int32_t child_byte_offset = 0; @@ -454,6 +454,7 @@ idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, @@ -499,7 +500,9 @@ StreamString s; ExecutionContext exe_ctx; this->GetExecutionContextScope()->CalculateExecutionContext(exe_ctx); - SymbolContext sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything); + SymbolContext sc; + if (exe_ctx.frame) + sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything); if (m_last_summary_format->m_show_members_oneliner) { @@ -1110,6 +1113,12 @@ } bool +ValueObject::IsArrayType () +{ + return ClangASTContext::IsArrayType (GetClangType()); +} + +bool ValueObject::IsScalarType () { return ClangASTContext::IsScalarType (GetClangType()); @@ -1171,6 +1180,49 @@ return synthetic_child_sp; } +// This allows you to create an array member using and index +// that doesn't not fall in the normal bounds of the array. +// Many times structure can be defined as: +// struct Collection +// { +// uint32_t item_count; +// Item item_array[0]; +// }; +// The size of the "item_array" is 1, but many times in practice +// there are more items in "item_array". + +ValueObjectSP +ValueObject::GetSyntheticArrayMemberFromArray (int32_t index, bool can_create) +{ + ValueObjectSP synthetic_child_sp; + if (IsArrayType ()) + { + char index_str[64]; + snprintf(index_str, sizeof(index_str), "[%i]", index); + ConstString index_const_str(index_str); + // Check if we have already created a synthetic array member in this + // valid object. If we have we will re-use it. + synthetic_child_sp = GetSyntheticChild (index_const_str); + if (!synthetic_child_sp) + { + ValueObject *synthetic_child; + // We haven't made a synthetic array member for INDEX yet, so + // lets make one and cache it for any future reference. + synthetic_child = CreateChildAtIndex(0, true, index); + + // Cache the value if we got one back... + if (synthetic_child) + { + AddSyntheticChild(index_const_str, synthetic_child); + synthetic_child_sp = synthetic_child->GetSP(); + synthetic_child_sp->SetName(index_str); + synthetic_child_sp->m_is_array_item_for_pointer = true; + } + } + } + return synthetic_child_sp; +} + ValueObjectSP ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create) { @@ -1628,20 +1680,23 @@ // from here on we do have a valid index if (ClangASTContext::IsArrayType(root_clang_type)) { - root = root->GetChildAtIndex(index, true); - if (!root.get()) + ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); + if (!child_valobj_sp) + child_valobj_sp = root->GetSyntheticArrayMemberFromArray(index, true); + if (child_valobj_sp) + { + root = child_valobj_sp; + *first_unparsed = end+1; // skip ] + *final_result = ValueObject::ePlain; + continue; + } + else { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eNoSuchChild; *final_result = ValueObject::eInvalid; return ValueObjectSP(); } - else - { - *first_unparsed = end+1; // skip ] - *final_result = ValueObject::ePlain; - continue; - } } else if (ClangASTContext::IsPointerType(root_clang_type)) { @@ -2057,6 +2112,7 @@ if (is_pointer_type) { bool omit_empty_base_classes = true; + bool ignore_array_bounds = false; std::string child_name_str; uint32_t child_byte_size = 0; @@ -2080,6 +2136,7 @@ 0, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=134846&r1=134845&r2=134846&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ClangASTContext.cpp (original) +++ lldb/trunk/source/Symbol/ClangASTContext.cpp Sat Jul 9 15:12:33 2011 @@ -2460,6 +2460,7 @@ uint32_t idx, bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string& child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, @@ -2478,6 +2479,7 @@ idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -2498,6 +2500,7 @@ uint32_t idx, bool transparent_pointers, bool omit_empty_base_classes, + bool ignore_array_bounds, std::string& child_name, uint32_t &child_byte_size, int32_t &child_byte_offset, @@ -2736,6 +2739,7 @@ idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -2771,7 +2775,7 @@ const ConstantArrayType *array = cast(parent_qual_type.getTypePtr()); const uint64_t element_count = array->getSize().getLimitedValue(); - if (idx < element_count) + if (ignore_array_bounds || idx < element_count) { if (GetCompleteQualType (ast, array->getElementType())) { @@ -2783,7 +2787,7 @@ child_name.assign(element_name); assert(field_type_info.first % 8 == 0); child_byte_size = field_type_info.first / 8; - child_byte_offset = idx * child_byte_size; + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; return array->getElementType().getAsOpaquePtr(); } } @@ -2810,6 +2814,7 @@ idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -2858,6 +2863,7 @@ idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, @@ -2895,6 +2901,7 @@ idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name, child_byte_size, child_byte_offset, Modified: lldb/trunk/source/Symbol/Variable.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Variable.cpp?rev=134846&r1=134845&r2=134846&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Variable.cpp (original) +++ lldb/trunk/source/Symbol/Variable.cpp Sat Jul 9 15:12:33 2011 @@ -199,10 +199,10 @@ return frame != NULL; case eValueTypeConstResult: - return true; - case eValueTypeVariableGlobal: case eValueTypeVariableStatic: + return true; + case eValueTypeVariableArgument: case eValueTypeVariableLocal: if (frame) From gclayton at apple.com Sun Jul 10 12:32:34 2011 From: gclayton at apple.com (Greg Clayton) Date: Sun, 10 Jul 2011 17:32:34 -0000 Subject: [Lldb-commits] [lldb] r134872 - /lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Message-ID: <20110710173234.274432A6C12C@llvm.org> Author: gclayton Date: Sun Jul 10 12:32:33 2011 New Revision: 134872 URL: http://llvm.org/viewvc/llvm-project?rev=134872&view=rev Log: Fixed an assertion crasher. We now handle things correclty and emit an error to stderr when we see this issue. Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Modified: lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp?rev=134872&r1=134871&r2=134872&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp Sun Jul 10 12:32:33 2011 @@ -675,9 +675,15 @@ { Section *section = m_section_list->FindSectionByID (n_sect).get(); m_section_infos[n_sect].section = section; - assert (section != NULL); - m_section_infos[n_sect].vm_range.SetBaseAddress (section->GetFileAddress()); - m_section_infos[n_sect].vm_range.SetByteSize (section->GetByteSize()); + if (section != NULL) + { + m_section_infos[n_sect].vm_range.SetBaseAddress (section->GetFileAddress()); + m_section_infos[n_sect].vm_range.SetByteSize (section->GetByteSize()); + } + else + { + fprintf (stderr, "error: unable to find section for section %u\n", n_sect); + } } if (m_section_infos[n_sect].vm_range.Contains(file_addr)) return m_section_infos[n_sect].section; From gclayton at apple.com Sun Jul 10 14:21:23 2011 From: gclayton at apple.com (Greg Clayton) Date: Sun, 10 Jul 2011 19:21:23 -0000 Subject: [Lldb-commits] [lldb] r134878 - in /lldb/trunk: include/lldb/Symbol/Declaration.h include/lldb/Symbol/SymbolContext.h include/lldb/Symbol/Variable.h source/Commands/CommandObjectFrame.cpp source/Commands/CommandObjectTarget.cpp source/Core/ValueObject.cpp source/Symbol/Declaration.cpp source/Symbol/SymbolContext.cpp source/Symbol/Variable.cpp Message-ID: <20110710192124.08C842A6C12C@llvm.org> Author: gclayton Date: Sun Jul 10 14:21:23 2011 New Revision: 134878 URL: http://llvm.org/viewvc/llvm-project?rev=134878&view=rev Log: Allow the built in ValueObject summary providers for C strings use lldb_private::Target::ReadMemory(...) to allow constant strings to be displayed in global variables prior on in between process execution. Centralized the variable declaration dumping into: bool Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module); Fixed an issue if you used "target variable --regex " where the variable name would not be displayed, but the regular expression would. Fixed an issue when viewing global variables through "target variable" might not display correctly when doing DWARF in object files. Modified: lldb/trunk/include/lldb/Symbol/Declaration.h lldb/trunk/include/lldb/Symbol/SymbolContext.h lldb/trunk/include/lldb/Symbol/Variable.h lldb/trunk/source/Commands/CommandObjectFrame.cpp lldb/trunk/source/Commands/CommandObjectTarget.cpp lldb/trunk/source/Core/ValueObject.cpp lldb/trunk/source/Symbol/Declaration.cpp lldb/trunk/source/Symbol/SymbolContext.cpp lldb/trunk/source/Symbol/Variable.cpp Modified: lldb/trunk/include/lldb/Symbol/Declaration.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Declaration.h?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/Declaration.h (original) +++ lldb/trunk/include/lldb/Symbol/Declaration.h Sun Jul 10 14:21:23 2011 @@ -141,7 +141,7 @@ void Dump (Stream *s, bool show_fullpaths) const; - void + bool DumpStopContext (Stream *s, bool show_fullpaths) const; //------------------------------------------------------------------ /// Get accessor for the declaration column number. Modified: lldb/trunk/include/lldb/Symbol/SymbolContext.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolContext.h?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/SymbolContext.h (original) +++ lldb/trunk/include/lldb/Symbol/SymbolContext.h Sun Jul 10 14:21:23 2011 @@ -160,7 +160,7 @@ /// @param[in] so_addr /// The resolved section offset address. //------------------------------------------------------------------ - void + bool DumpStopContext (Stream *s, ExecutionContextScope *exe_scope, const Address &so_addr, Modified: lldb/trunk/include/lldb/Symbol/Variable.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Variable.h?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/Variable.h (original) +++ lldb/trunk/include/lldb/Symbol/Variable.h Sun Jul 10 14:21:23 2011 @@ -44,6 +44,11 @@ void Dump(Stream *s, bool show_context) const; + bool + DumpDeclaration (Stream *s, + bool show_fullpaths, + bool show_module); + const Declaration& GetDeclaration() const { Modified: lldb/trunk/source/Commands/CommandObjectFrame.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectFrame.cpp?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectFrame.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectFrame.cpp Sun Jul 10 14:21:23 2011 @@ -479,8 +479,10 @@ if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) { - var_sp->GetDeclaration ().DumpStopContext (&s, false); - s.PutCString (": "); + bool show_fullpaths = false; + bool show_module = true; + if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) + s.PutCString (": "); } ValueObject::DumpValueObject (result.GetOutputStream(), Modified: lldb/trunk/source/Commands/CommandObjectTarget.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectTarget.cpp?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp (original) +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp Sun Jul 10 14:21:23 2011 @@ -466,10 +466,12 @@ break; } - if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile()) + if (m_option_variable.show_decl) { - var_sp->GetDeclaration ().DumpStopContext (&s, false); - s.PutCString (": "); + bool show_fullpaths = false; + bool show_module = true; + if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) + s.PutCString (": "); } const Format format = m_option_variable.format; @@ -528,6 +530,7 @@ const char *arg = args.GetArgumentAtIndex(idx); uint32_t matches = 0; + bool use_var_name = false; if (m_option_variable.use_regex) { RegularExpression regex(arg); @@ -537,6 +540,7 @@ result.SetStatus (eReturnStatusFailed); return false; } + use_var_name = true; matches = exe_ctx.target->GetImages().FindGlobalVariables (regex, true, UINT32_MAX, @@ -573,10 +577,10 @@ { ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx)); if (!valobj_sp) - valobj_sp = ValueObjectVariable::Create (exe_ctx.target, var_sp); + valobj_sp = ValueObjectVariable::Create (exe_ctx.GetBestExecutionContextScope(), var_sp); if (valobj_sp) - DumpValueObject (s, var_sp, valobj_sp, arg); + DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg); } } } Modified: lldb/trunk/source/Core/ValueObject.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/source/Core/ValueObject.cpp (original) +++ lldb/trunk/source/Core/ValueObject.cpp Sun Jul 10 14:21:23 2011 @@ -563,8 +563,8 @@ if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && ClangASTContext::IsCharType (elem_or_pointee_clang_type)) { - Process *process = exe_scope->CalculateProcess(); - if (process != NULL) + Target *target = exe_scope->CalculateTarget(); + if (target != NULL) { lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; AddressType cstr_address_type = eAddressTypeInvalid; @@ -593,15 +593,21 @@ } if (cstr_address != LLDB_INVALID_ADDRESS) { + Address cstr_so_addr (NULL, cstr_address); DataExtractor data; size_t bytes_read = 0; std::vector data_buffer; Error error; + bool prefer_file_cache = false; if (cstr_len > 0) { data_buffer.resize(cstr_len); data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); - bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), cstr_len, error); + bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + cstr_len, + error); if (bytes_read > 0) { sstr << '"'; @@ -629,7 +635,11 @@ sstr << '"'; data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); - while ((bytes_read = process->ReadMemory (cstr_address, &data_buffer.front(), k_max_buf_size, error)) > 0) + while ((bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + k_max_buf_size, + error)) > 0) { size_t len = strlen(&data_buffer.front()); if (len == 0) @@ -649,7 +659,7 @@ if (len < k_max_buf_size) break; - cstr_address += k_max_buf_size; + cstr_so_addr.Slide (k_max_buf_size); } sstr << '"'; } Modified: lldb/trunk/source/Symbol/Declaration.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Declaration.cpp?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Declaration.cpp (original) +++ lldb/trunk/source/Symbol/Declaration.cpp Sun Jul 10 14:21:23 2011 @@ -46,7 +46,7 @@ } } -void +bool Declaration::DumpStopContext (Stream *s, bool show_fullpaths) const { if (m_file) @@ -62,15 +62,18 @@ if (m_column > 0) s->Printf(":%u", m_column); #endif + return true; } - else + else if (m_line > 0) { s->Printf(" line %u", m_line); #ifdef LLDB_ENABLE_DECLARATION_COLUMNS if (m_column > 0) s->Printf(":%u", m_column); #endif + return true; } + return false; } size_t Modified: lldb/trunk/source/Symbol/SymbolContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolContext.cpp?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/source/Symbol/SymbolContext.cpp (original) +++ lldb/trunk/source/Symbol/SymbolContext.cpp Sun Jul 10 14:21:23 2011 @@ -110,7 +110,7 @@ symbol = NULL; } -void +bool SymbolContext::DumpStopContext ( Stream *s, @@ -121,6 +121,7 @@ bool show_inlined_frames ) const { + bool dumped_something = false; if (show_module && module_sp) { if (show_fullpaths) @@ -128,18 +129,25 @@ else *s << module_sp->GetFileSpec().GetFilename(); s->PutChar('`'); + dumped_something = true; } if (function != NULL) { if (function->GetMangled().GetName()) + { + dumped_something = true; function->GetMangled().GetName().Dump(s); + } if (addr.IsValid()) { const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset(); if (function_offset) - s->Printf(" + %llu", function_offset); + { + dumped_something = true; + s->Printf(" + %llu", function_offset); + } } if (block != NULL) @@ -147,11 +155,13 @@ s->IndentMore(); block->DumpStopContext (s, this, NULL, show_fullpaths, show_inlined_frames); s->IndentLess(); + dumped_something = true; } else { if (line_entry.IsValid()) { + dumped_something = true; s->PutCString(" at "); if (line_entry.DumpStopContext(s, show_fullpaths)) return; @@ -160,19 +170,28 @@ } else if (symbol != NULL) { - symbol->GetMangled().GetName().Dump(s); + if (symbol->GetMangled().GetName()) + { + dumped_something = true; + symbol->GetMangled().GetName().Dump(s); + } if (addr.IsValid() && symbol->GetAddressRangePtr()) { const addr_t symbol_offset = addr.GetOffset() - symbol->GetAddressRangePtr()->GetBaseAddress().GetOffset(); if (symbol_offset) - s->Printf(" + %llu", symbol_offset); + { + dumped_something = true; + s->Printf(" + %llu", symbol_offset); + } } } else if (addr.IsValid()) { addr.Dump(s, exe_scope, Address::DumpStyleModuleWithFileAddress); + dumped_something = true; } + return dumped_something; } void Modified: lldb/trunk/source/Symbol/Variable.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Variable.cpp?rev=134878&r1=134877&r2=134878&view=diff ============================================================================== --- lldb/trunk/source/Symbol/Variable.cpp (original) +++ lldb/trunk/source/Symbol/Variable.cpp Sun Jul 10 14:21:23 2011 @@ -142,6 +142,32 @@ s->EOL(); } +bool +Variable::DumpDeclaration (Stream *s, bool show_fullpaths, bool show_module) +{ + bool dumped_declaration_info = false; + if (m_owner_scope) + { + SymbolContext sc; + m_owner_scope->CalculateSymbolContext(&sc); + sc.block = NULL; + sc.line_entry.Clear(); + bool show_inlined_frames = false; + + dumped_declaration_info = sc.DumpStopContext (s, + NULL, + Address(), + show_fullpaths, + show_module, + show_inlined_frames); + + if (sc.function) + s->PutChar(':'); + } + if (m_declaration.DumpStopContext (s, false)) + dumped_declaration_info = true; + return dumped_declaration_info; +} size_t Variable::MemorySize() const