diff options
Diffstat (limited to 'include/lldb')
339 files changed, 83266 insertions, 0 deletions
diff --git a/include/lldb/API/LLDB.h b/include/lldb/API/LLDB.h new file mode 100644 index 0000000..93bc3bc --- /dev/null +++ b/include/lldb/API/LLDB.h @@ -0,0 +1,54 @@ +//===-- LLDB.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_LLDB_h_ +#define LLDB_LLDB_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBAddress.h" +#include "lldb/API/SBBlock.h" +#include "lldb/API/SBBreakpoint.h" +#include "lldb/API/SBBreakpointLocation.h" +#include "lldb/API/SBBroadcaster.h" +#include "lldb/API/SBCommandInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBCommunication.h" +#include "lldb/API/SBCompileUnit.h" +#include "lldb/API/SBData.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBDeclaration.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBEvent.h" +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBFrame.h" +#include "lldb/API/SBFunction.h" +#include "lldb/API/SBHostOS.h" +#include "lldb/API/SBInputReader.h" +#include "lldb/API/SBInstruction.h" +#include "lldb/API/SBInstructionList.h" +#include "lldb/API/SBLineEntry.h" +#include "lldb/API/SBListener.h" +#include "lldb/API/SBModule.h" +#include "lldb/API/SBProcess.h" +#include "lldb/API/SBSourceManager.h" +#include "lldb/API/SBStream.h" +#include "lldb/API/SBStringList.h" +#include "lldb/API/SBSymbol.h" +#include "lldb/API/SBSymbolContext.h" +#include "lldb/API/SBTarget.h" +#include "lldb/API/SBThread.h" +#include "lldb/API/SBType.h" +#include "lldb/API/SBValue.h" +#include "lldb/API/SBValueList.h" + +#endif // LLDB_LLDB_h_ diff --git a/include/lldb/API/SBAddress.h b/include/lldb/API/SBAddress.h new file mode 100644 index 0000000..c5e8cc6 --- /dev/null +++ b/include/lldb/API/SBAddress.h @@ -0,0 +1,150 @@ +//===-- SBAddress.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_SBAddress_h_ +#define LLDB_SBAddress_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBModule.h" + +namespace lldb { + +class SBAddress +{ +public: + + SBAddress (); + + SBAddress (const lldb::SBAddress &rhs); + + SBAddress (lldb::SBSection section, lldb::addr_t offset); + + // Create an address by resolving a load address using the supplied target + SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target); + + ~SBAddress (); + + const lldb::SBAddress & + operator = (const lldb::SBAddress &rhs); + + bool + IsValid () const; + + void + Clear (); + + addr_t + GetFileAddress () const; + + addr_t + GetLoadAddress (const lldb::SBTarget &target) const; + + void + SetAddress (lldb::SBSection section, lldb::addr_t offset); + + void + SetLoadAddress (lldb::addr_t load_addr, + lldb::SBTarget &target); + bool + OffsetAddress (addr_t offset); + + bool + GetDescription (lldb::SBStream &description); + + // The following queries can lookup symbol information for a given address. + // An address might refer to code or data from an existing module, or it + // might refer to something on the stack or heap. The following functions + // will only return valid values if the address has been resolved to a code + // or data address using "void SBAddress::SetLoadAddress(...)" or + // "lldb::SBAddress SBTarget::ResolveLoadAddress (...)". + lldb::SBSymbolContext + GetSymbolContext (uint32_t resolve_scope); + + + // The following functions grab individual objects for a given address and + // are less efficient if you want more than one symbol related objects. + // Use one of the following when you want multiple debug symbol related + // objects for an address: + // lldb::SBSymbolContext SBAddress::GetSymbolContext (uint32_t resolve_scope); + // lldb::SBSymbolContext SBTarget::ResolveSymbolContextForAddress (const SBAddress &addr, uint32_t resolve_scope); + // One or more bits from the SymbolContextItem enumerations can be logically + // OR'ed together to more efficiently retrieve multiple symbol objects. + + lldb::SBSection + GetSection (); + + lldb::addr_t + GetOffset (); + + lldb::SBModule + GetModule (); + + lldb::SBCompileUnit + GetCompileUnit (); + + lldb::SBFunction + GetFunction (); + + lldb::SBBlock + GetBlock (); + + lldb::SBSymbol + GetSymbol (); + + lldb::SBLineEntry + GetLineEntry (); + + lldb::AddressClass + GetAddressClass (); + +protected: + + friend class SBBlock; + friend class SBBreakpointLocation; + friend class SBFrame; + friend class SBFunction; + friend class SBLineEntry; + friend class SBInstruction; + friend class SBModule; + friend class SBSection; + friend class SBSymbol; + friend class SBSymbolContext; + friend class SBTarget; + friend class SBThread; + friend class SBValue; + + lldb_private::Address * + operator->(); + + const lldb_private::Address * + operator->() const; + + lldb_private::Address * + get (); + + lldb_private::Address & + ref(); + + const lldb_private::Address & + ref() const; + + SBAddress (const lldb_private::Address *lldb_object_ptr); + + void + SetAddress (const lldb_private::Address *lldb_object_ptr); + +private: + + std::unique_ptr<lldb_private::Address> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBAddress_h_ diff --git a/include/lldb/API/SBBlock.h b/include/lldb/API/SBBlock.h new file mode 100644 index 0000000..b8e61fc --- /dev/null +++ b/include/lldb/API/SBBlock.h @@ -0,0 +1,123 @@ +//===-- SBBlock.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_SBBlock_h_ +#define LLDB_SBBlock_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBFrame.h" +#include "lldb/API/SBTarget.h" +#include "lldb/API/SBValueList.h" + +namespace lldb { + +class SBBlock +{ +public: + + SBBlock (); + + SBBlock (const lldb::SBBlock &rhs); + + ~SBBlock (); + + const lldb::SBBlock & + operator = (const lldb::SBBlock &rhs); + + bool + IsInlined () const; + + bool + IsValid () const; + + const char * + GetInlinedName () const; + + lldb::SBFileSpec + GetInlinedCallSiteFile () const; + + uint32_t + GetInlinedCallSiteLine () const; + + uint32_t + GetInlinedCallSiteColumn () const; + + lldb::SBBlock + GetParent (); + + lldb::SBBlock + GetSibling (); + + lldb::SBBlock + GetFirstChild (); + + uint32_t + GetNumRanges (); + + lldb::SBAddress + GetRangeStartAddress (uint32_t idx); + + lldb::SBAddress + GetRangeEndAddress (uint32_t idx); + + uint32_t + GetRangeIndexForBlockAddress (lldb::SBAddress block_addr); + + lldb::SBValueList + GetVariables (lldb::SBFrame& frame, + bool arguments, + bool locals, + bool statics, + lldb::DynamicValueType use_dynamic); + + lldb::SBValueList + GetVariables (lldb::SBTarget& target, + bool arguments, + bool locals, + bool statics); + //------------------------------------------------------------------ + /// Get the inlined block that contains this block. + /// + /// @return + /// If this block is inlined, it will return this block, else + /// parent blocks will be searched to see if any contain this + /// block and are themselves inlined. An invalid SBBlock will + /// be returned if this block nor any parent blocks are inlined + /// function blocks. + //------------------------------------------------------------------ + lldb::SBBlock + GetContainingInlinedBlock (); + + bool + GetDescription (lldb::SBStream &description); + +private: + friend class SBAddress; + friend class SBFrame; + friend class SBFunction; + friend class SBSymbolContext; + + lldb_private::Block * + GetPtr (); + + void + SetPtr (lldb_private::Block *lldb_object_ptr); + + SBBlock (lldb_private::Block *lldb_object_ptr); + + void + AppendVariables (bool can_create, bool get_parent_variables, lldb_private::VariableList *var_list); + + lldb_private::Block *m_opaque_ptr; +}; + + +} // namespace lldb + +#endif // LLDB_SBBlock_h_ diff --git a/include/lldb/API/SBBreakpoint.h b/include/lldb/API/SBBreakpoint.h new file mode 100644 index 0000000..be9c499 --- /dev/null +++ b/include/lldb/API/SBBreakpoint.h @@ -0,0 +1,175 @@ +//===-- SBBreakpoint.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_SBBreakpoint_h_ +#define LLDB_SBBreakpoint_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBBreakpoint +{ +public: + + typedef bool (*BreakpointHitCallback) (void *baton, + SBProcess &process, + SBThread &thread, + lldb::SBBreakpointLocation &location); + + SBBreakpoint (); + + SBBreakpoint (const lldb::SBBreakpoint& rhs); + + ~SBBreakpoint(); + + const lldb::SBBreakpoint & + operator = (const lldb::SBBreakpoint& rhs); + + // Tests to see if the opaque breakpoint object in this object matches the + // opaque breakpoint object in "rhs". + bool + operator == (const lldb::SBBreakpoint& rhs); + + bool + operator != (const lldb::SBBreakpoint& rhs); + + break_id_t + GetID () const; + + bool + IsValid() const; + + void + ClearAllBreakpointSites (); + + lldb::SBBreakpointLocation + FindLocationByAddress (lldb::addr_t vm_addr); + + lldb::break_id_t + FindLocationIDByAddress (lldb::addr_t vm_addr); + + lldb::SBBreakpointLocation + FindLocationByID (lldb::break_id_t bp_loc_id); + + lldb::SBBreakpointLocation + GetLocationAtIndex (uint32_t index); + + void + SetEnabled (bool enable); + + bool + IsEnabled (); + + void + SetOneShot (bool one_shot); + + bool + IsOneShot () const; + + bool + IsInternal (); + + uint32_t + GetHitCount () const; + + void + SetIgnoreCount (uint32_t count); + + uint32_t + GetIgnoreCount () const; + + void + SetCondition (const char *condition); + + const char * + GetCondition (); + + void + SetThreadID (lldb::tid_t sb_thread_id); + + lldb::tid_t + GetThreadID (); + + void + SetThreadIndex (uint32_t index); + + uint32_t + GetThreadIndex() const; + + void + SetThreadName (const char *thread_name); + + const char * + GetThreadName () const; + + void + SetQueueName (const char *queue_name); + + const char * + GetQueueName () const; + + void + SetCallback (BreakpointHitCallback callback, void *baton); + + size_t + GetNumResolvedLocations() const; + + size_t + GetNumLocations() const; + + bool + GetDescription (lldb::SBStream &description); + + static bool + EventIsBreakpointEvent (const lldb::SBEvent &event); + + static lldb::BreakpointEventType + GetBreakpointEventTypeFromEvent (const lldb::SBEvent& event); + + static lldb::SBBreakpoint + GetBreakpointFromEvent (const lldb::SBEvent& event); + + static lldb::SBBreakpointLocation + GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx); + + static uint32_t + GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp); + + +private: + friend class SBBreakpointLocation; + friend class SBTarget; + + SBBreakpoint (const lldb::BreakpointSP &bp_sp); + + lldb_private::Breakpoint * + operator->() const; + + lldb_private::Breakpoint * + get() const; + + lldb::BreakpointSP & + operator *(); + + const lldb::BreakpointSP & + operator *() const; + + static bool + PrivateBreakpointHitCallback (void *baton, + lldb_private::StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + lldb::BreakpointSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBBreakpoint_h_ diff --git a/include/lldb/API/SBBreakpointLocation.h b/include/lldb/API/SBBreakpointLocation.h new file mode 100644 index 0000000..3b2ca2c --- /dev/null +++ b/include/lldb/API/SBBreakpointLocation.h @@ -0,0 +1,110 @@ +//===-- SBBreakpointLocation.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_SBBreakpointLocation_h_ +#define LLDB_SBBreakpointLocation_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBBreakpoint.h" + +namespace lldb { + +class SBBreakpointLocation +{ +public: + + SBBreakpointLocation (); + + SBBreakpointLocation (const lldb::SBBreakpointLocation &rhs); + + ~SBBreakpointLocation (); + + const lldb::SBBreakpointLocation & + operator = (const lldb::SBBreakpointLocation &rhs); + + break_id_t + GetID (); + + bool + IsValid() const; + + lldb::SBAddress + GetAddress (); + + lldb::addr_t + GetLoadAddress (); + + void + SetEnabled(bool enabled); + + bool + IsEnabled (); + + uint32_t + GetIgnoreCount (); + + void + SetIgnoreCount (uint32_t n); + + void + SetCondition (const char *condition); + + const char * + GetCondition (); + + void + SetThreadID (lldb::tid_t sb_thread_id); + + lldb::tid_t + GetThreadID (); + + void + SetThreadIndex (uint32_t index); + + uint32_t + GetThreadIndex() const; + + void + SetThreadName (const char *thread_name); + + const char * + GetThreadName () const; + + void + SetQueueName (const char *queue_name); + + const char * + GetQueueName () const; + + bool + IsResolved (); + + bool + GetDescription (lldb::SBStream &description, DescriptionLevel level); + + SBBreakpoint + GetBreakpoint (); + + SBBreakpointLocation (const lldb::BreakpointLocationSP &break_loc_sp); + +private: + friend class SBBreakpoint; +#ifndef LLDB_DISABLE_PYTHON + friend class lldb_private::ScriptInterpreterPython; +#endif + void + SetLocation (const lldb::BreakpointLocationSP &break_loc_sp); + + lldb::BreakpointLocationSP m_opaque_sp; + +}; + +} // namespace lldb + +#endif // LLDB_SBBreakpointLocation_h_ diff --git a/include/lldb/API/SBBroadcaster.h b/include/lldb/API/SBBroadcaster.h new file mode 100644 index 0000000..7b32d85 --- /dev/null +++ b/include/lldb/API/SBBroadcaster.h @@ -0,0 +1,97 @@ +//===-- SBBroadcaster.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_SBBroadcaster_h_ +#define LLDB_SBBroadcaster_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBBroadcaster +{ +public: + SBBroadcaster (); + + SBBroadcaster (const char *name); + + SBBroadcaster (const SBBroadcaster &rhs); + + const SBBroadcaster & + operator = (const SBBroadcaster &rhs); + + ~SBBroadcaster(); + + bool + IsValid () const; + + void + Clear (); + + void + BroadcastEventByType (uint32_t event_type, bool unique = false); + + void + BroadcastEvent (const lldb::SBEvent &event, bool unique = false); + + void + AddInitialEventsToListener (const lldb::SBListener &listener, uint32_t requested_events); + + uint32_t + AddListener (const lldb::SBListener &listener, uint32_t event_mask); + + const char * + GetName () const; + + bool + EventTypeHasListeners (uint32_t event_type); + + bool + RemoveListener (const lldb::SBListener &listener, uint32_t event_mask = UINT32_MAX); + + // This comparison is checking if the internal opaque pointer value + // is equal to that in "rhs". + bool + operator == (const lldb::SBBroadcaster &rhs) const; + + // This comparison is checking if the internal opaque pointer value + // is not equal to that in "rhs". + bool + operator != (const lldb::SBBroadcaster &rhs) const; + + // This comparison is checking if the internal opaque pointer value + // is less than that in "rhs" so SBBroadcaster objects can be contained + // in ordered containers. + bool + operator < (const lldb::SBBroadcaster &rhs) const; + +protected: + friend class SBCommandInterpreter; + friend class SBCommunication; + friend class SBEvent; + friend class SBListener; + friend class SBProcess; + friend class SBTarget; + + SBBroadcaster (lldb_private::Broadcaster *broadcaster, bool owns); + + lldb_private::Broadcaster * + get () const; + + void + reset (lldb_private::Broadcaster *broadcaster, bool owns); + +private: + lldb::BroadcasterSP m_opaque_sp; + lldb_private::Broadcaster *m_opaque_ptr; +}; + +} // namespace lldb + +#endif // LLDB_SBBroadcaster_h_ diff --git a/include/lldb/API/SBCommandInterpreter.h b/include/lldb/API/SBCommandInterpreter.h new file mode 100644 index 0000000..9b2583c --- /dev/null +++ b/include/lldb/API/SBCommandInterpreter.h @@ -0,0 +1,193 @@ +//===-- SBCommandInterpreter.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_SBCommandInterpreter_h_ +#define LLDB_SBCommandInterpreter_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBDebugger.h" + +namespace lldb { + +class SBCommandInterpreter +{ +public: + enum + { + eBroadcastBitThreadShouldExit = (1 << 0), + eBroadcastBitResetPrompt = (1 << 1), + eBroadcastBitQuitCommandReceived = (1 << 2), // User entered quit + eBroadcastBitAsynchronousOutputData = (1 << 3), + eBroadcastBitAsynchronousErrorData = (1 << 4) + }; + + SBCommandInterpreter (const lldb::SBCommandInterpreter &rhs); + + const lldb::SBCommandInterpreter & + operator = (const lldb::SBCommandInterpreter &rhs); + + ~SBCommandInterpreter (); + + static const char * + GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type); + + static const char * + GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type); + + bool + IsValid() const; + + bool + CommandExists (const char *cmd); + + bool + AliasExists (const char *cmd); + + lldb::SBBroadcaster + GetBroadcaster (); + + static const char * + GetBroadcasterClass (); + + bool + HasCommands (); + + bool + HasAliases (); + + bool + HasAliasOptions (); + + lldb::SBProcess + GetProcess (); + + lldb::SBDebugger + GetDebugger (); + + lldb::SBCommand + AddMultiwordCommand (const char* name, const char* help); + + lldb::SBCommand + AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, const char* help); + + void + SourceInitFileInHomeDirectory (lldb::SBCommandReturnObject &result); + + void + SourceInitFileInCurrentWorkingDirectory (lldb::SBCommandReturnObject &result); + + lldb::ReturnStatus + HandleCommand (const char *command_line, lldb::SBCommandReturnObject &result, bool add_to_history = false); + + // The pointer based interface is not useful in SWIG, since the cursor & last_char arguments are string pointers INTO current_line + // and you can't do that in a scripting language interface in general... + + // In either case, the way this works is that the you give it a line and cursor position in the line. The function + // will return the number of completions. The matches list will contain number_of_completions + 1 elements. The first + // element is the common substring after the cursor position for all the matches. The rest of the elements are the + // matches. The first element is useful if you are emulating the common shell behavior where the tab completes + // to the string that is common among all the matches, then you should first check if the first element is non-empty, + // and if so just insert it and move the cursor to the end of the insertion. The next tab will return an empty + // common substring, and a list of choices (if any), at which point you should display the choices and let the user + // type further to disambiguate. + + int + HandleCompletion (const char *current_line, + const char *cursor, + const char *last_char, + int match_start_point, + int max_return_elements, + lldb::SBStringList &matches); + + int + HandleCompletion (const char *current_line, + uint32_t cursor_pos, + int match_start_point, + int max_return_elements, + lldb::SBStringList &matches); + + // Catch commands before they execute by registering a callback that will + // get called when the command gets executed. This allows GUI or command + // line interfaces to intercept a command and stop it from happening + bool + SetCommandOverrideCallback (const char *command_name, + lldb::CommandOverrideCallback callback, + void *baton); + + SBCommandInterpreter (lldb_private::CommandInterpreter *interpreter_ptr = NULL); // Access using SBDebugger::GetCommandInterpreter(); + +protected: + + lldb_private::CommandInterpreter & + ref (); + + lldb_private::CommandInterpreter * + get (); + + void + reset (lldb_private::CommandInterpreter *); +private: + friend class SBDebugger; + + static void + InitializeSWIG (); + + lldb_private::CommandInterpreter *m_opaque_ptr; +}; + +class SBCommandPluginInterface +{ +public: + virtual bool + DoExecute (lldb::SBDebugger debugger, + char** command, + lldb::SBCommandReturnObject &result) + { + return false; + } + + virtual + ~SBCommandPluginInterface () + {} +}; + +class SBCommand +{ +public: + + SBCommand (); + + bool + IsValid (); + + const char* + GetName (); + + const char* + GetHelp (); + + lldb::SBCommand + AddMultiwordCommand (const char* name, const char* help = NULL); + + lldb::SBCommand + AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help = NULL); + +private: + + friend class SBDebugger; + friend class SBCommandInterpreter; + + SBCommand (lldb::CommandObjectSP cmd_sp); + + lldb::CommandObjectSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBCommandInterpreter_h_ diff --git a/include/lldb/API/SBCommandReturnObject.h b/include/lldb/API/SBCommandReturnObject.h new file mode 100644 index 0000000..f2d2748 --- /dev/null +++ b/include/lldb/API/SBCommandReturnObject.h @@ -0,0 +1,133 @@ +//===-- SBCommandReturnObject.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_SBCommandReturnObject_h_ +#define LLDB_SBCommandReturnObject_h_ + +#include <stdio.h> + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBCommandReturnObject +{ +public: + + SBCommandReturnObject (); + + SBCommandReturnObject (const lldb::SBCommandReturnObject &rhs); + + const lldb::SBCommandReturnObject & + operator = (const lldb::SBCommandReturnObject &rhs); + + + SBCommandReturnObject (lldb_private::CommandReturnObject *ptr); + + lldb_private::CommandReturnObject * + Release (); + + ~SBCommandReturnObject (); + + bool + IsValid() const; + + const char * + GetOutput (); + + const char * + GetError (); + + size_t + PutOutput (FILE *fh); + + size_t + GetOutputSize (); + + size_t + GetErrorSize (); + + size_t + PutError (FILE *fh); + + void + Clear(); + + lldb::ReturnStatus + GetStatus(); + + void + SetStatus (lldb::ReturnStatus status); + + bool + Succeeded (); + + bool + HasResult (); + + void + AppendMessage (const char *message); + + void + AppendWarning (const char *message); + + bool + GetDescription (lldb::SBStream &description); + + void + SetImmediateOutputFile (FILE *fh); + + void + SetImmediateErrorFile (FILE *fh); + + void + PutCString(const char* string, int len = -1); + + size_t + Printf(const char* format, ...) __attribute__ ((format (printf, 2, 3))); + + const char * + GetOutput (bool only_if_no_immediate); + + const char * + GetError (bool only_if_no_immediate); + + void + SetError (lldb::SBError &error, + const char *fallback_error_cstr = NULL); + + void + SetError (const char* error_cstr); + +protected: + friend class SBCommandInterpreter; + friend class SBOptions; + + lldb_private::CommandReturnObject * + operator->() const; + + lldb_private::CommandReturnObject * + get() const; + + lldb_private::CommandReturnObject & + operator*() const; + + lldb_private::CommandReturnObject & + ref() const; + + void + SetLLDBObjectPtr (lldb_private::CommandReturnObject *ptr); + + private: + std::unique_ptr<lldb_private::CommandReturnObject> m_opaque_ap; +}; + +} // namespace lldb + +#endif // LLDB_SBCommandReturnObject_h_ diff --git a/include/lldb/API/SBCommunication.h b/include/lldb/API/SBCommunication.h new file mode 100644 index 0000000..ecaaa35 --- /dev/null +++ b/include/lldb/API/SBCommunication.h @@ -0,0 +1,99 @@ +//===-- SBCommunication.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_SBCommunication_h_ +#define LLDB_SBCommunication_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBError.h" + +namespace lldb { + +class SBCommunication +{ +public: + enum { + eBroadcastBitDisconnected = (1 << 0), ///< Sent when the communications connection is lost. + eBroadcastBitReadThreadGotBytes = (1 << 1), ///< Sent by the read thread when bytes become available. + eBroadcastBitReadThreadDidExit = (1 << 2), ///< Sent by the read thread when it exits to inform clients. + eBroadcastBitReadThreadShouldExit = (1 << 3), ///< Sent by clients that need to cancel the read thread. + eBroadcastBitPacketAvailable = (1 << 4), ///< Sent when data received makes a complete packet. + eAllEventBits = 0xffffffff + }; + + typedef void (*ReadThreadBytesReceived) (void *baton, const void *src, size_t src_len); + + SBCommunication (); + SBCommunication (const char * broadcaster_name); + ~SBCommunication (); + + + bool + IsValid () const; + + lldb::SBBroadcaster + GetBroadcaster (); + + static const char *GetBroadcasterClass(); + + lldb::ConnectionStatus + AdoptFileDesriptor (int fd, bool owns_fd); + + lldb::ConnectionStatus + Connect (const char *url); + + lldb::ConnectionStatus + Disconnect (); + + bool + IsConnected () const; + + bool + GetCloseOnEOF (); + + void + SetCloseOnEOF (bool b); + + size_t + Read (void *dst, + size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status); + + size_t + Write (const void *src, + size_t src_len, + lldb::ConnectionStatus &status); + + bool + ReadThreadStart (); + + bool + ReadThreadStop (); + + bool + ReadThreadIsRunning (); + + bool + SetReadThreadBytesReceivedCallback (ReadThreadBytesReceived callback, + void *callback_baton); + + +private: + + DISALLOW_COPY_AND_ASSIGN (SBCommunication); + + lldb_private::Communication *m_opaque; + bool m_opaque_owned; +}; + + +} // namespace lldb + +#endif // LLDB_SBCommunication_h_ diff --git a/include/lldb/API/SBCompileUnit.h b/include/lldb/API/SBCompileUnit.h new file mode 100644 index 0000000..95af3d4 --- /dev/null +++ b/include/lldb/API/SBCompileUnit.h @@ -0,0 +1,116 @@ +//===-- SBCompileUnit.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_SBCompileUnit_h_ +#define LLDB_SBCompileUnit_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBFileSpec.h" + +namespace lldb { + +class SBCompileUnit +{ +public: + + SBCompileUnit (); + + SBCompileUnit (const lldb::SBCompileUnit &rhs); + + ~SBCompileUnit (); + + const lldb::SBCompileUnit & + operator = (const lldb::SBCompileUnit &rhs); + + bool + IsValid () const; + + lldb::SBFileSpec + GetFileSpec () const; + + uint32_t + GetNumLineEntries () const; + + lldb::SBLineEntry + GetLineEntryAtIndex (uint32_t idx) const; + + uint32_t + FindLineEntryIndex (uint32_t start_idx, + uint32_t line, + lldb::SBFileSpec *inline_file_spec) const; + + uint32_t + FindLineEntryIndex (uint32_t start_idx, + uint32_t line, + lldb::SBFileSpec *inline_file_spec, + bool exact) const; + + SBFileSpec + GetSupportFileAtIndex (uint32_t idx) const; + + uint32_t + GetNumSupportFiles () const; + + uint32_t + FindSupportFileIndex (uint32_t start_idx, const SBFileSpec &sb_file, bool full); + + //------------------------------------------------------------------ + /// Get all types matching \a type_mask from debug info in this + /// compile unit. + /// + /// @param[in] type_mask + /// A bitfield that consists of one or more bits logically OR'ed + /// together from the lldb::TypeClass enumeration. This allows + /// you to request only structure types, or only class, struct + /// and union types. Passing in lldb::eTypeClassAny will return + /// all types found in the debug information for this compile + /// unit. + /// + /// @return + /// A list of types in this compile unit that match \a type_mask + //------------------------------------------------------------------ + lldb::SBTypeList + GetTypes (uint32_t type_mask = lldb::eTypeClassAny); + + bool + operator == (const lldb::SBCompileUnit &rhs) const; + + bool + operator != (const lldb::SBCompileUnit &rhs) const; + + bool + GetDescription (lldb::SBStream &description); + +private: + friend class SBAddress; + friend class SBFrame; + friend class SBSymbolContext; + friend class SBModule; + + SBCompileUnit (lldb_private::CompileUnit *lldb_object_ptr); + + const lldb_private::CompileUnit * + operator->() const; + + const lldb_private::CompileUnit & + operator*() const; + + lldb_private::CompileUnit * + get (); + + void + reset (lldb_private::CompileUnit *lldb_object_ptr); + + lldb_private::CompileUnit *m_opaque_ptr; +}; + + +} // namespace lldb + +#endif // LLDB_SBCompileUnit_h_ diff --git a/include/lldb/API/SBData.h b/include/lldb/API/SBData.h new file mode 100644 index 0000000..10c0022 --- /dev/null +++ b/include/lldb/API/SBData.h @@ -0,0 +1,180 @@ +//===-- SBData.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_SBData_h_ +#define LLDB_SBData_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBData +{ +public: + + SBData (); + + SBData (const SBData &rhs); + + const SBData & + operator = (const SBData &rhs); + + ~SBData (); + + uint8_t + GetAddressByteSize (); + + void + SetAddressByteSize (uint8_t addr_byte_size); + + void + Clear (); + + bool + IsValid(); + + size_t + GetByteSize (); + + lldb::ByteOrder + GetByteOrder(); + + void + SetByteOrder (lldb::ByteOrder endian); + + float + GetFloat (lldb::SBError& error, lldb::offset_t offset); + + double + GetDouble (lldb::SBError& error, lldb::offset_t offset); + + long double + GetLongDouble (lldb::SBError& error, lldb::offset_t offset); + + lldb::addr_t + GetAddress (lldb::SBError& error, lldb::offset_t offset); + + uint8_t + GetUnsignedInt8 (lldb::SBError& error, lldb::offset_t offset); + + uint16_t + GetUnsignedInt16 (lldb::SBError& error, lldb::offset_t offset); + + uint32_t + GetUnsignedInt32 (lldb::SBError& error, lldb::offset_t offset); + + uint64_t + GetUnsignedInt64 (lldb::SBError& error, lldb::offset_t offset); + + int8_t + GetSignedInt8 (lldb::SBError& error, lldb::offset_t offset); + + int16_t + GetSignedInt16 (lldb::SBError& error, lldb::offset_t offset); + + int32_t + GetSignedInt32 (lldb::SBError& error, lldb::offset_t offset); + + int64_t + GetSignedInt64 (lldb::SBError& error, lldb::offset_t offset); + + const char* + GetString (lldb::SBError& error, lldb::offset_t offset); + + size_t + ReadRawData (lldb::SBError& error, + lldb::offset_t offset, + void *buf, + size_t size); + + bool + GetDescription (lldb::SBStream &description, lldb::addr_t base_addr = LLDB_INVALID_ADDRESS); + + // it would be nice to have SetData(SBError, const void*, size_t) when endianness and address size can be + // inferred from the existing DataExtractor, but having two SetData() signatures triggers a SWIG bug where + // the typemap isn't applied before resolving the overload, and thus the right function never gets called + void + SetData (lldb::SBError& error, const void *buf, size_t size, lldb::ByteOrder endian, uint8_t addr_size); + + // see SetData() for why we don't have Append(const void* buf, size_t size) + bool + Append (const SBData& rhs); + + static lldb::SBData + CreateDataFromCString (lldb::ByteOrder endian, uint32_t addr_byte_size, const char* data); + + // in the following CreateData*() and SetData*() prototypes, the two parameters array and array_len + // should not be renamed or rearranged, because doing so will break the SWIG typemap + static lldb::SBData + CreateDataFromUInt64Array (lldb::ByteOrder endian, uint32_t addr_byte_size, uint64_t* array, size_t array_len); + + static lldb::SBData + CreateDataFromUInt32Array (lldb::ByteOrder endian, uint32_t addr_byte_size, uint32_t* array, size_t array_len); + + static lldb::SBData + CreateDataFromSInt64Array (lldb::ByteOrder endian, uint32_t addr_byte_size, int64_t* array, size_t array_len); + + static lldb::SBData + CreateDataFromSInt32Array (lldb::ByteOrder endian, uint32_t addr_byte_size, int32_t* array, size_t array_len); + + static lldb::SBData + CreateDataFromDoubleArray (lldb::ByteOrder endian, uint32_t addr_byte_size, double* array, size_t array_len); + + bool + SetDataFromCString (const char* data); + + bool + SetDataFromUInt64Array (uint64_t* array, size_t array_len); + + bool + SetDataFromUInt32Array (uint32_t* array, size_t array_len); + + bool + SetDataFromSInt64Array (int64_t* array, size_t array_len); + + bool + SetDataFromSInt32Array (int32_t* array, size_t array_len); + + bool + SetDataFromDoubleArray (double* array, size_t array_len); + + +protected: + + // Mimic shared pointer... + lldb_private::DataExtractor * + get() const; + + lldb_private::DataExtractor * + operator->() const; + + lldb::DataExtractorSP & + operator*(); + + const lldb::DataExtractorSP & + operator*() const; + + SBData (const lldb::DataExtractorSP &data_sp); + + void + SetOpaque (const lldb::DataExtractorSP &data_sp); + +private: + friend class SBInstruction; + friend class SBProcess; + friend class SBSection; + friend class SBValue; + + lldb::DataExtractorSP m_opaque_sp; +}; + + +} // namespace lldb + +#endif // LLDB_SBData_h_ diff --git a/include/lldb/API/SBDebugger.h b/include/lldb/API/SBDebugger.h new file mode 100644 index 0000000..518cbf6 --- /dev/null +++ b/include/lldb/API/SBDebugger.h @@ -0,0 +1,339 @@ +//===-- SBDebugger.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_SBDebugger_h_ +#define LLDB_SBDebugger_h_ + +#include "lldb/API/SBDefines.h" +#include <stdio.h> + +namespace lldb { + +class SBDebugger +{ +public: + + static void + Initialize(); + + static void + Terminate(); + + // Deprecated, use the one that takes a source_init_files bool. + static lldb::SBDebugger + Create(); + + static lldb::SBDebugger + Create(bool source_init_files); + + static lldb::SBDebugger + Create(bool source_init_files, lldb::LogOutputCallback log_callback, void *baton); + + static void + Destroy (lldb::SBDebugger &debugger); + + static void + MemoryPressureDetected (); + + SBDebugger(); + + SBDebugger(const lldb::SBDebugger &rhs); + + SBDebugger(const lldb::DebuggerSP &debugger_sp); + + lldb::SBDebugger & + operator = (const lldb::SBDebugger &rhs); + + ~SBDebugger(); + + bool + IsValid() const; + + void + Clear (); + + void + SetAsync (bool b); + + bool + GetAsync (); + + void + SkipLLDBInitFiles (bool b); + + void + SkipAppInitFiles (bool b); + + void + SetInputFileHandle (FILE *f, bool transfer_ownership); + + void + SetOutputFileHandle (FILE *f, bool transfer_ownership); + + void + SetErrorFileHandle (FILE *f, bool transfer_ownership); + + FILE * + GetInputFileHandle (); + + FILE * + GetOutputFileHandle (); + + FILE * + GetErrorFileHandle (); + + void + SaveInputTerminalState(); + + void + RestoreInputTerminalState(); + + lldb::SBCommandInterpreter + GetCommandInterpreter (); + + void + HandleCommand (const char *command); + + lldb::SBListener + GetListener (); + + void + HandleProcessEvent (const lldb::SBProcess &process, + const lldb::SBEvent &event, + FILE *out, + FILE *err); + + lldb::SBTarget + CreateTarget (const char *filename, + const char *target_triple, + const char *platform_name, + bool add_dependent_modules, + lldb::SBError& error); + + lldb::SBTarget + CreateTargetWithFileAndTargetTriple (const char *filename, + const char *target_triple); + + lldb::SBTarget + CreateTargetWithFileAndArch (const char *filename, + const char *archname); + + lldb::SBTarget + CreateTarget (const char *filename); + + // Return true if target is deleted from the target list of the debugger. + bool + DeleteTarget (lldb::SBTarget &target); + + lldb::SBTarget + GetTargetAtIndex (uint32_t idx); + + uint32_t + GetIndexOfTarget (lldb::SBTarget target); + + lldb::SBTarget + FindTargetWithProcessID (pid_t pid); + + lldb::SBTarget + FindTargetWithFileAndArch (const char *filename, + const char *arch); + + uint32_t + GetNumTargets (); + + lldb::SBTarget + GetSelectedTarget (); + + void + SetSelectedTarget (SBTarget& target); + + lldb::SBSourceManager + GetSourceManager (); + + // REMOVE: just for a quick fix, need to expose platforms through + // SBPlatform from this class. + lldb::SBError + SetCurrentPlatform (const char *platform_name); + + bool + SetCurrentPlatformSDKRoot (const char *sysroot); + + // FIXME: Once we get the set show stuff in place, the driver won't need + // an interface to the Set/Get UseExternalEditor. + bool + SetUseExternalEditor (bool input); + + bool + GetUseExternalEditor (); + + bool + SetUseColor (bool use_color); + + bool + GetUseColor () const; + + static bool + GetDefaultArchitecture (char *arch_name, size_t arch_name_len); + + static bool + SetDefaultArchitecture (const char *arch_name); + + lldb::ScriptLanguage + GetScriptingLanguage (const char *script_language_name); + + static const char * + GetVersionString (); + + static const char * + StateAsCString (lldb::StateType state); + + static bool + StateIsRunningState (lldb::StateType state); + + static bool + StateIsStoppedState (lldb::StateType state); + + bool + EnableLog (const char *channel, const char **categories); + + void + SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton); + + // DEPRECATED + void + DispatchInput (void* baton, + const void* data, + size_t data_len); + + void + DispatchInput (const void *data, size_t data_len); + + void + DispatchInputInterrupt (); + + void + DispatchInputEndOfFile (); + + void + PushInputReader (lldb::SBInputReader &reader); + + void + NotifyTopInputReader (lldb::InputReaderAction notification); + + bool + InputReaderIsTopReader (const lldb::SBInputReader &reader); + + const char * + GetInstanceName (); + + static SBDebugger + FindDebuggerWithID (int id); + + static lldb::SBError + SetInternalVariable (const char *var_name, const char *value, const char *debugger_instance_name); + + static lldb::SBStringList + GetInternalVariableValue (const char *var_name, const char *debugger_instance_name); + + bool + GetDescription (lldb::SBStream &description); + + uint32_t + GetTerminalWidth () const; + + void + SetTerminalWidth (uint32_t term_width); + + lldb::user_id_t + GetID (); + + const char * + GetPrompt() const; + + void + SetPrompt (const char *prompt); + + lldb::ScriptLanguage + GetScriptLanguage() const; + + void + SetScriptLanguage (lldb::ScriptLanguage script_lang); + + bool + GetCloseInputOnEOF () const; + + void + SetCloseInputOnEOF (bool b); + + SBTypeCategory + GetCategory (const char* category_name); + + SBTypeCategory + CreateCategory (const char* category_name); + + bool + DeleteCategory (const char* category_name); + + uint32_t + GetNumCategories (); + + SBTypeCategory + GetCategoryAtIndex (uint32_t); + + SBTypeCategory + GetDefaultCategory(); + + SBTypeFormat + GetFormatForType (SBTypeNameSpecifier); + +#ifndef LLDB_DISABLE_PYTHON + SBTypeSummary + GetSummaryForType (SBTypeNameSpecifier); +#endif + + SBTypeFilter + GetFilterForType (SBTypeNameSpecifier); + +#ifndef LLDB_DISABLE_PYTHON + SBTypeSynthetic + GetSyntheticForType (SBTypeNameSpecifier); +#endif + +private: + + friend class SBCommandInterpreter; + friend class SBInputReader; + friend class SBListener; + friend class SBProcess; + friend class SBSourceManager; + friend class SBTarget; + + lldb::SBTarget + FindTargetWithLLDBProcess (const lldb::ProcessSP &processSP); + + void + reset (const lldb::DebuggerSP &debugger_sp); + + lldb_private::Debugger * + get () const; + + lldb_private::Debugger & + ref () const; + + const lldb::DebuggerSP & + get_sp () const; + + lldb::DebuggerSP m_opaque_sp; + +}; // class SBDebugger + + +} // namespace lldb + +#endif // LLDB_SBDebugger_h_ diff --git a/include/lldb/API/SBDeclaration.h b/include/lldb/API/SBDeclaration.h new file mode 100644 index 0000000..190026c --- /dev/null +++ b/include/lldb/API/SBDeclaration.h @@ -0,0 +1,89 @@ +//===-- SBDeclaration.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_SBDeclaration_h_ +#define LLDB_SBDeclaration_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBFileSpec.h" + +namespace lldb { + + class SBDeclaration + { + public: + + SBDeclaration (); + + SBDeclaration (const lldb::SBDeclaration &rhs); + + ~SBDeclaration (); + + const lldb::SBDeclaration & + operator = (const lldb::SBDeclaration &rhs); + + bool + IsValid () const; + + lldb::SBFileSpec + GetFileSpec () const; + + uint32_t + GetLine () const; + + uint32_t + GetColumn () const; + + void + SetFileSpec (lldb::SBFileSpec filespec); + + void + SetLine (uint32_t line); + + void + SetColumn (uint32_t column); + + bool + operator == (const lldb::SBDeclaration &rhs) const; + + bool + operator != (const lldb::SBDeclaration &rhs) const; + + bool + GetDescription (lldb::SBStream &description); + + protected: + + lldb_private::Declaration * + get (); + + private: + friend class SBValue; + + const lldb_private::Declaration * + operator->() const; + + lldb_private::Declaration & + ref(); + + const lldb_private::Declaration & + ref() const; + + SBDeclaration (const lldb_private::Declaration *lldb_object_ptr); + + void + SetDeclaration (const lldb_private::Declaration &lldb_object_ref); + + std::unique_ptr<lldb_private::Declaration> m_opaque_ap; + }; + + +} // namespace lldb + +#endif // LLDB_SBDeclaration_h_ diff --git a/include/lldb/API/SBDefines.h b/include/lldb/API/SBDefines.h new file mode 100644 index 0000000..2cdf921 --- /dev/null +++ b/include/lldb/API/SBDefines.h @@ -0,0 +1,84 @@ +//===-- SBDefines.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_SBDefines_h_ +#define LLDB_SBDefines_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" +#include "lldb/lldb-versioning.h" + +// Forward Declarations + +namespace lldb { + +class SBAddress; +class SBBlock; +class SBBreakpoint; +class SBBreakpointLocation; +class SBBroadcaster; +class SBCommand; +class SBCommandInterpreter; +class SBCommandPluginInterface; +class SBCommandReturnObject; +class SBCommunication; +class SBCompileUnit; +class SBData; +class SBDebugger; +class SBDeclaration; +class SBError; +class SBEvent; +class SBEventList; +class SBExpressionOptions; +class SBFileSpec; +class SBFileSpecList; +class SBFrame; +class SBFunction; +class SBHostOS; +class SBInputReader; +class SBInstruction; +class SBInstructionList; +class SBLineEntry; +class SBListener; +class SBModule; +class SBModuleSpec; +class SBModuleSpecList; +class SBProcess; +class SBSourceManager; +class SBStream; +class SBStringList; +class SBSymbol; +class SBSymbolContext; +class SBSymbolContextList; +class SBTarget; +class SBThread; +class SBType; +class SBTypeCategory; +class SBTypeFilter; +class SBTypeFormat; +class SBTypeNameSpecifier; +class SBTypeSummary; +#ifndef LLDB_DISABLE_PYTHON +class SBTypeSynthetic; +#endif +class SBTypeList; +class SBValue; +class SBValueList; +class SBWatchpoint; + +} + +#endif // LLDB_SBDefines_h_ diff --git a/include/lldb/API/SBError.h b/include/lldb/API/SBError.h new file mode 100644 index 0000000..a6d3dac --- /dev/null +++ b/include/lldb/API/SBError.h @@ -0,0 +1,106 @@ +//===-- SBError.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_SBError_h_ +#define LLDB_SBError_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBError { +public: + SBError (); + + SBError (const lldb::SBError &rhs); + + ~SBError(); + + const SBError & + operator =(const lldb::SBError &rhs); + + const char * + GetCString () const; + + void + Clear (); + + bool + Fail () const; + + bool + Success () const; + + uint32_t + GetError () const; + + lldb::ErrorType + GetType () const; + + void + SetError (uint32_t err, lldb::ErrorType type); + + void + SetErrorToErrno (); + + void + SetErrorToGenericError (); + + void + SetErrorString (const char *err_str); + + int + SetErrorStringWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + bool + IsValid () const; + + bool + GetDescription (lldb::SBStream &description); + +protected: + + friend class SBCommandReturnObject; + friend class SBData; + friend class SBDebugger; + friend class SBCommunication; + friend class SBHostOS; + friend class SBInputReader; + friend class SBProcess; + friend class SBThread; + friend class SBTarget; + friend class SBValue; + friend class SBWatchpoint; + + lldb_private::Error * + get(); + + lldb_private::Error * + operator->(); + + const lldb_private::Error & + operator*() const; + + lldb_private::Error & + ref(); + + void + SetError (const lldb_private::Error &lldb_error); + +private: + std::unique_ptr<lldb_private::Error> m_opaque_ap; + + void + CreateIfNeeded (); +}; + + +} // namespace lldb + +#endif // LLDB_SBError_h_ diff --git a/include/lldb/API/SBEvent.h b/include/lldb/API/SBEvent.h new file mode 100644 index 0000000..6cb975a --- /dev/null +++ b/include/lldb/API/SBEvent.h @@ -0,0 +1,102 @@ +//===-- SBEvent.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_SBEvent_h_ +#define LLDB_SBEvent_h_ + +#include "lldb/API/SBDefines.h" + +#include <stdio.h> +#include <vector> + + +namespace lldb { + +class SBBroadcaster; + +class SBEvent +{ +public: + SBEvent(); + + SBEvent (const lldb::SBEvent &rhs); + + // Make an event that contains a C string. + SBEvent (uint32_t event, const char *cstr, uint32_t cstr_len); + + ~SBEvent(); + + const SBEvent & + operator = (const lldb::SBEvent &rhs); + + bool + IsValid() const; + + const char * + GetDataFlavor (); + + uint32_t + GetType () const; + + lldb::SBBroadcaster + GetBroadcaster () const; + + const char * + GetBroadcasterClass () const; + + bool + BroadcasterMatchesPtr (const lldb::SBBroadcaster *broadcaster); + + bool + BroadcasterMatchesRef (const lldb::SBBroadcaster &broadcaster); + + void + Clear(); + + static const char * + GetCStringFromEvent (const lldb::SBEvent &event); + + bool + GetDescription (lldb::SBStream &description); + + bool + GetDescription (lldb::SBStream &description) const; + +protected: + friend class SBListener; + friend class SBBroadcaster; + friend class SBBreakpoint; + friend class SBDebugger; + friend class SBProcess; + friend class SBThread; + friend class SBWatchpoint; + + SBEvent (lldb::EventSP &event_sp); + + lldb::EventSP & + GetSP () const; + + void + reset (lldb::EventSP &event_sp); + + void + reset (lldb_private::Event* event); + + lldb_private::Event * + get () const; + +private: + + mutable lldb::EventSP m_event_sp; + mutable lldb_private::Event *m_opaque_ptr; +}; + +} // namespace lldb + +#endif // LLDB_SBEvent_h_ diff --git a/include/lldb/API/SBExpressionOptions.h b/include/lldb/API/SBExpressionOptions.h new file mode 100644 index 0000000..eed9ed5 --- /dev/null +++ b/include/lldb/API/SBExpressionOptions.h @@ -0,0 +1,89 @@ +//===-- SBEvent.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_SBExpressionOptions_h_ +#define LLDB_SBExpressionOptions_h_ + +#include "lldb/API/SBDefines.h" + +#include <vector> + +namespace lldb { + + +class SBExpressionOptions +{ +public: + SBExpressionOptions(); + + SBExpressionOptions (const lldb::SBExpressionOptions &rhs); + + ~SBExpressionOptions(); + + const SBExpressionOptions & + operator = (const lldb::SBExpressionOptions &rhs); + + bool + GetCoerceResultToId () const; + + void + SetCoerceResultToId (bool coerce = true); + + bool + GetUnwindOnError () const; + + void + SetUnwindOnError (bool unwind = true); + + bool + GetIgnoreBreakpoints () const; + + void + SetIgnoreBreakpoints (bool ignore = true); + + lldb::DynamicValueType + GetFetchDynamicValue () const; + + void + SetFetchDynamicValue (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget); + + uint32_t + GetTimeoutInMicroSeconds () const; + + void + SetTimeoutInMicroSeconds (uint32_t timeout = 0); + + bool + GetTryAllThreads () const; + + void + SetTryAllThreads (bool run_others = true); + +protected: + + SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options); + + lldb_private::EvaluateExpressionOptions * + get () const; + + lldb_private::EvaluateExpressionOptions & + ref () const; + + friend class SBFrame; + friend class SBValue; + friend class SBTarget; + +private: + // This auto_pointer is made in the constructor and is always valid. + mutable std::unique_ptr<lldb_private::EvaluateExpressionOptions> m_opaque_ap; +}; + +} // namespace lldb + +#endif // LLDB_SBExpressionOptions_h_ diff --git a/include/lldb/API/SBFileSpec.h b/include/lldb/API/SBFileSpec.h new file mode 100644 index 0000000..e44abe4 --- /dev/null +++ b/include/lldb/API/SBFileSpec.h @@ -0,0 +1,96 @@ +//===-- SBFileSpec.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_SBFileSpec_h_ +#define LLDB_SBFileSpec_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBFileSpec +{ +public: + SBFileSpec (); + + SBFileSpec (const lldb::SBFileSpec &rhs); + + SBFileSpec (const char *path);// Deprected, use SBFileSpec (const char *path, bool resolve) + + SBFileSpec (const char *path, bool resolve); + + ~SBFileSpec (); + + const SBFileSpec & + operator = (const lldb::SBFileSpec &rhs); + + bool + IsValid() const; + + bool + Exists () const; + + bool + ResolveExecutableLocation (); + + const char * + GetFilename() const; + + const char * + GetDirectory() const; + + uint32_t + GetPath (char *dst_path, size_t dst_len) const; + + static int + ResolvePath (const char *src_path, char *dst_path, size_t dst_len); + + bool + GetDescription (lldb::SBStream &description) const; + +private: + friend class SBAttachInfo; + friend class SBBlock; + friend class SBCompileUnit; + friend class SBDeclaration; + friend class SBFileSpecList; + friend class SBHostOS; + friend class SBLaunchInfo; + friend class SBLineEntry; + friend class SBModule; + friend class SBModuleSpec; + friend class SBProcess; + friend class SBSourceManager; + friend class SBThread; + friend class SBTarget; + + SBFileSpec (const lldb_private::FileSpec& fspec); + + void + SetFileSpec (const lldb_private::FileSpec& fspec); + + const lldb_private::FileSpec * + operator->() const; + + const lldb_private::FileSpec * + get() const; + + const lldb_private::FileSpec & + operator*() const; + + const lldb_private::FileSpec & + ref() const; + + std::unique_ptr<lldb_private::FileSpec> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBFileSpec_h_ diff --git a/include/lldb/API/SBFileSpecList.h b/include/lldb/API/SBFileSpecList.h new file mode 100644 index 0000000..734e7d4 --- /dev/null +++ b/include/lldb/API/SBFileSpecList.h @@ -0,0 +1,72 @@ +//===-- SBFileSpecList.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_SBFileSpecList_h_ +#define LLDB_SBFileSpecList_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBFileSpecList +{ +public: + SBFileSpecList (); + + SBFileSpecList (const lldb::SBFileSpecList &rhs); + + ~SBFileSpecList (); + + const SBFileSpecList & + operator = (const lldb::SBFileSpecList &rhs); + + uint32_t + GetSize () const; + + bool + GetDescription (SBStream &description) const; + + void + Append (const SBFileSpec &sb_file); + + bool + AppendIfUnique (const SBFileSpec &sb_file); + + void + Clear(); + + uint32_t + FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full); + + const SBFileSpec + GetFileSpecAtIndex (uint32_t idx) const; + +private: + +friend class SBTarget; + + const lldb_private::FileSpecList * + operator->() const; + + const lldb_private::FileSpecList * + get() const; + + const lldb_private::FileSpecList & + operator*() const; + + const lldb_private::FileSpecList & + ref() const; + + std::unique_ptr<lldb_private::FileSpecList> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBFileSpecList_h_ diff --git a/include/lldb/API/SBFrame.h b/include/lldb/API/SBFrame.h new file mode 100644 index 0000000..4ae38c1 --- /dev/null +++ b/include/lldb/API/SBFrame.h @@ -0,0 +1,242 @@ +//===-- SBFrame.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_SBFrame_h_ +#define LLDB_SBFrame_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBValueList.h" + +namespace lldb { + +class SBFrame +{ +public: + SBFrame (); + + SBFrame (const lldb::SBFrame &rhs); + + const lldb::SBFrame & + operator =(const lldb::SBFrame &rhs); + + ~SBFrame(); + + bool + IsEqual (const lldb::SBFrame &that) const; + + bool + IsValid() const; + + uint32_t + GetFrameID () const; + + lldb::addr_t + GetPC () const; + + bool + SetPC (lldb::addr_t new_pc); + + lldb::addr_t + GetSP () const; + + lldb::addr_t + GetFP () const; + + lldb::SBAddress + GetPCAddress () const; + + lldb::SBSymbolContext + GetSymbolContext (uint32_t resolve_scope) const; + + lldb::SBModule + GetModule () const; + + lldb::SBCompileUnit + GetCompileUnit () const; + + lldb::SBFunction + GetFunction () const; + + lldb::SBSymbol + GetSymbol () const; + + /// Gets the deepest block that contains the frame PC. + /// + /// See also GetFrameBlock(). + lldb::SBBlock + GetBlock () const; + + /// Get the appropriate function name for this frame. Inlined functions in + /// LLDB are represented by Blocks that have inlined function information, so + /// just looking at the SBFunction or SBSymbol for a frame isn't enough. + /// This function will return the appriopriate function, symbol or inlined + /// function name for the frame. + /// + /// This function returns: + /// - the name of the inlined function (if there is one) + /// - the name of the concrete function (if there is one) + /// - the name of the symbol (if there is one) + /// - NULL + /// + /// See also IsInlined(). + const char * + GetFunctionName(); + + /// Return true if this frame represents an inlined function. + /// + /// See also GetFunctionName(). + bool + IsInlined(); + + /// The version that doesn't supply a 'use_dynamic' value will use the + /// target's default. + lldb::SBValue + EvaluateExpression (const char *expr); + + lldb::SBValue + EvaluateExpression (const char *expr, lldb::DynamicValueType use_dynamic); + + lldb::SBValue + EvaluateExpression (const char *expr, lldb::DynamicValueType use_dynamic, bool unwind_on_error); + + lldb::SBValue + EvaluateExpression (const char *expr, const SBExpressionOptions &options); + + /// Gets the lexical block that defines the stack frame. Another way to think + /// of this is it will return the block that contains all of the variables + /// for a stack frame. Inlined functions are represented as SBBlock objects + /// that have inlined function information: the name of the inlined function, + /// where it was called from. The block that is returned will be the first + /// block at or above the block for the PC (SBFrame::GetBlock()) that defines + /// the scope of the frame. When a function contains no inlined functions, + /// this will be the top most lexical block that defines the function. + /// When a function has inlined functions and the PC is currently + /// in one of those inlined functions, this method will return the inlined + /// block that defines this frame. If the PC isn't currently in an inlined + /// function, the lexical block that defines the function is returned. + lldb::SBBlock + GetFrameBlock () const; + + lldb::SBLineEntry + GetLineEntry () const; + + lldb::SBThread + GetThread () const; + + const char * + Disassemble () const; + + void + Clear(); + + bool + operator == (const lldb::SBFrame &rhs) const; + + bool + operator != (const lldb::SBFrame &rhs) const; + + /// The version that doesn't supply a 'use_dynamic' value will use the + /// target's default. + lldb::SBValueList + GetVariables (bool arguments, + bool locals, + bool statics, + bool in_scope_only); + + lldb::SBValueList + GetVariables (bool arguments, + bool locals, + bool statics, + bool in_scope_only, + lldb::DynamicValueType use_dynamic); + + lldb::SBValueList + GetRegisters (); + + lldb::SBValue + FindRegister (const char *name); + + /// The version that doesn't supply a 'use_dynamic' value will use the + /// target's default. + lldb::SBValue + FindVariable (const char *var_name); + + lldb::SBValue + FindVariable (const char *var_name, lldb::DynamicValueType use_dynamic); + + // Find a value for a variable expression path like "rect.origin.x" or + // "pt_ptr->x", "*self", "*this->obj_ptr". The returned value is _not_ + // and expression result and is not a constant object like + // SBFrame::EvaluateExpression(...) returns, but a child object of + // the variable value. + lldb::SBValue + GetValueForVariablePath (const char *var_expr_cstr, + DynamicValueType use_dynamic); + + /// The version that doesn't supply a 'use_dynamic' value will use the + /// target's default. + lldb::SBValue + GetValueForVariablePath (const char *var_path); + + /// Find variables, register sets, registers, or persistent variables using + /// the frame as the scope. + /// + /// NB. This function does not look up ivars in the function object pointer. + /// To do that use GetValueForVariablePath. + /// + /// The version that doesn't supply a 'use_dynamic' value will use the + /// target's default. + lldb::SBValue + FindValue (const char *name, ValueType value_type); + + lldb::SBValue + FindValue (const char *name, ValueType value_type, lldb::DynamicValueType use_dynamic); + + /// Find and watch a variable using the frame as the scope. + /// It returns an SBValue, similar to FindValue() method, if find-and-watch + /// operation succeeds. Otherwise, an invalid SBValue is returned. + /// You can use LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE for 'rw' watch. + lldb::SBValue + WatchValue (const char *name, ValueType value_type, uint32_t watch_type); + + /// Find and watch the location pointed to by a variable using the frame as + /// the scope. + /// It returns an SBValue, similar to FindValue() method, if find-and-watch + /// operation succeeds. Otherwise, an invalid SBValue is returned. + /// You can use LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE for 'rw' watch. + lldb::SBValue + WatchLocation (const char *name, ValueType value_type, uint32_t watch_type, size_t size); + + bool + GetDescription (lldb::SBStream &description); + + SBFrame (const lldb::StackFrameSP &lldb_object_sp); + +protected: + + friend class SBBlock; + friend class SBInstruction; + friend class SBThread; + friend class SBValue; +#ifndef LLDB_DISABLE_PYTHON + friend class lldb_private::ScriptInterpreterPython; +#endif + + lldb::StackFrameSP + GetFrameSP() const; + + void + SetFrameSP (const lldb::StackFrameSP &lldb_object_sp); + + lldb::ExecutionContextRefSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBFrame_h_ diff --git a/include/lldb/API/SBFunction.h b/include/lldb/API/SBFunction.h new file mode 100644 index 0000000..49a3847 --- /dev/null +++ b/include/lldb/API/SBFunction.h @@ -0,0 +1,93 @@ +//===-- SBFunction.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_SBFunction_h_ +#define LLDB_SBFunction_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBAddress.h" +#include "lldb/API/SBInstructionList.h" + +namespace lldb { + +class SBFunction +{ +public: + + SBFunction (); + + SBFunction (const lldb::SBFunction &rhs); + + const lldb::SBFunction & + operator = (const lldb::SBFunction &rhs); + + ~SBFunction (); + + bool + IsValid () const; + + const char * + GetName() const; + + const char * + GetMangledName () const; + + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target); + + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target, const char *flavor); + + lldb::SBAddress + GetStartAddress (); + + lldb::SBAddress + GetEndAddress (); + + uint32_t + GetPrologueByteSize (); + + lldb::SBType + GetType (); + + lldb::SBBlock + GetBlock (); + + bool + operator == (const lldb::SBFunction &rhs) const; + + bool + operator != (const lldb::SBFunction &rhs) const; + + bool + GetDescription (lldb::SBStream &description); + +protected: + + lldb_private::Function * + get (); + + void + reset (lldb_private::Function *lldb_object_ptr); + +private: + friend class SBAddress; + friend class SBFrame; + friend class SBSymbolContext; + + SBFunction (lldb_private::Function *lldb_object_ptr); + + + lldb_private::Function *m_opaque_ptr; +}; + + +} // namespace lldb + +#endif // LLDB_SBFunction_h_ diff --git a/include/lldb/API/SBHostOS.h b/include/lldb/API/SBHostOS.h new file mode 100644 index 0000000..52754ea --- /dev/null +++ b/include/lldb/API/SBHostOS.h @@ -0,0 +1,57 @@ +//===-- SBHostOS.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_SBHostOS_h_ +#define LLDB_SBHostOS_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBFileSpec.h" + +namespace lldb { + +class SBHostOS +{ +public: + + static lldb::SBFileSpec + GetProgramFileSpec (); + + static lldb::SBFileSpec + GetLLDBPythonPath (); + + static void + ThreadCreated (const char *name); + + static lldb::thread_t + ThreadCreate (const char *name, + void *(*thread_function)(void *), + void *thread_arg, + lldb::SBError *err); + + static bool + ThreadCancel (lldb::thread_t thread, + lldb::SBError *err); + + static bool + ThreadDetach (lldb::thread_t thread, + lldb::SBError *err); + static bool + ThreadJoin (lldb::thread_t thread, + void **result, + lldb::SBError *err); + + +private: + +}; + + +} // namespace lldb + +#endif // LLDB_SBHostOS_h_ diff --git a/include/lldb/API/SBInputReader.h b/include/lldb/API/SBInputReader.h new file mode 100644 index 0000000..61f7de4 --- /dev/null +++ b/include/lldb/API/SBInputReader.h @@ -0,0 +1,97 @@ +//===-- SBInputReader.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_SBInputReader_h_ +#define LLDB_SBInputReader_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBInputReader +{ +public: + + typedef size_t (*Callback) (void *baton, + SBInputReader *reader, + InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + SBInputReader (); + + SBInputReader (const lldb::InputReaderSP &reader_sp); + + SBInputReader (const lldb::SBInputReader &rhs); + + ~SBInputReader (); + + + SBError + Initialize (SBDebugger &debugger, + Callback callback, + void *callback_baton, + lldb::InputReaderGranularity granularity, + const char *end_token, + const char *prompt, + bool echo); + + bool + IsValid () const; + + const lldb::SBInputReader & + operator = (const lldb::SBInputReader &rhs); + + bool + IsActive () const; + + bool + IsDone () const; + + void + SetIsDone (bool value); + + InputReaderGranularity + GetGranularity (); + +protected: + friend class SBDebugger; + + lldb_private::InputReader * + operator->() const; + + lldb::InputReaderSP & + operator *(); + + const lldb::InputReaderSP & + operator *() const; + + lldb_private::InputReader * + get() const; + + lldb_private::InputReader & + ref() const; + +private: + + static size_t + PrivateCallback (void *baton, + lldb_private::InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + lldb::InputReaderSP m_opaque_sp; + Callback m_callback_function; + void *m_callback_baton; +}; + +} // namespace lldb + +#endif // LLDB_SBInputReader_h_ diff --git a/include/lldb/API/SBInstruction.h b/include/lldb/API/SBInstruction.h new file mode 100644 index 0000000..aad2d87 --- /dev/null +++ b/include/lldb/API/SBInstruction.h @@ -0,0 +1,94 @@ +//===-- SBInstruction.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_SBInstruction_h_ +#define LLDB_SBInstruction_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBData.h" + +#include <stdio.h> + +// There's a lot to be fixed here, but need to wait for underlying insn implementation +// to be revised & settle down first. + +namespace lldb { + +class SBInstruction +{ +public: + + SBInstruction (); + + SBInstruction (const SBInstruction &rhs); + + const SBInstruction & + operator = (const SBInstruction &rhs); + + ~SBInstruction (); + + bool + IsValid(); + + SBAddress + GetAddress(); + + lldb::AddressClass + GetAddressClass (); + + const char * + GetMnemonic (lldb::SBTarget target); + + const char * + GetOperands (lldb::SBTarget target); + + const char * + GetComment (lldb::SBTarget target); + + lldb::SBData + GetData (lldb::SBTarget target); + + size_t + GetByteSize (); + + bool + DoesBranch (); + + void + Print (FILE *out); + + bool + GetDescription (lldb::SBStream &description); + + bool + EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options); + + bool + DumpEmulation (const char * triple); // triple is to specify the architecture, e.g. 'armv6' or 'armv7-apple-ios' + + bool + TestEmulation (lldb::SBStream &output_stream, const char *test_file); + +protected: + friend class SBInstructionList; + + SBInstruction (const lldb::InstructionSP &inst_sp); + + void + SetOpaque (const lldb::InstructionSP &inst_sp); + +private: + + lldb::InstructionSP m_opaque_sp; +}; + + +} // namespace lldb + +#endif // LLDB_SBInstruction_h_ diff --git a/include/lldb/API/SBInstructionList.h b/include/lldb/API/SBInstructionList.h new file mode 100644 index 0000000..944e144 --- /dev/null +++ b/include/lldb/API/SBInstructionList.h @@ -0,0 +1,71 @@ +//===-- SBInstructionList.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_SBInstructionList_h_ +#define LLDB_SBInstructionList_h_ + +#include "lldb/API/SBDefines.h" + +#include <stdio.h> + +namespace lldb { + +class SBInstructionList +{ +public: + + SBInstructionList (); + + SBInstructionList (const SBInstructionList &rhs); + + const SBInstructionList & + operator = (const SBInstructionList &rhs); + + ~SBInstructionList (); + + bool + IsValid () const; + + size_t + GetSize (); + + lldb::SBInstruction + GetInstructionAtIndex (uint32_t idx); + + void + Clear (); + + void + AppendInstruction (lldb::SBInstruction inst); + + void + Print (FILE *out); + + bool + GetDescription (lldb::SBStream &description); + + bool + DumpEmulationForAllInstructions (const char *triple); + +protected: + friend class SBFunction; + friend class SBSymbol; + friend class SBTarget; + + void + SetDisassembler (const lldb::DisassemblerSP &opaque_sp); + +private: + lldb::DisassemblerSP m_opaque_sp; +}; + + +} // namespace lldb + +#endif // LLDB_SBInstructionList_h_ diff --git a/include/lldb/API/SBLineEntry.h b/include/lldb/API/SBLineEntry.h new file mode 100644 index 0000000..2d099a2 --- /dev/null +++ b/include/lldb/API/SBLineEntry.h @@ -0,0 +1,99 @@ +//===-- SBLineEntry.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_SBLineEntry_h_ +#define LLDB_SBLineEntry_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBAddress.h" +#include "lldb/API/SBFileSpec.h" + +namespace lldb { + +class SBLineEntry +{ +public: + + SBLineEntry (); + + SBLineEntry (const lldb::SBLineEntry &rhs); + + ~SBLineEntry (); + + const lldb::SBLineEntry & + operator = (const lldb::SBLineEntry &rhs); + + lldb::SBAddress + GetStartAddress () const; + + lldb::SBAddress + GetEndAddress () const; + + bool + IsValid () const; + + lldb::SBFileSpec + GetFileSpec () const; + + uint32_t + GetLine () const; + + uint32_t + GetColumn () const; + + void + SetFileSpec (lldb::SBFileSpec filespec); + + void + SetLine (uint32_t line); + + void + SetColumn (uint32_t column); + + bool + operator == (const lldb::SBLineEntry &rhs) const; + + bool + operator != (const lldb::SBLineEntry &rhs) const; + + bool + GetDescription (lldb::SBStream &description); + +protected: + + lldb_private::LineEntry * + get (); + +private: + friend class SBAddress; + friend class SBCompileUnit; + friend class SBFrame; + friend class SBSymbolContext; + + const lldb_private::LineEntry * + operator->() const; + + lldb_private::LineEntry & + ref(); + + const lldb_private::LineEntry & + ref() const; + + SBLineEntry (const lldb_private::LineEntry *lldb_object_ptr); + + void + SetLineEntry (const lldb_private::LineEntry &lldb_object_ref); + + std::unique_ptr<lldb_private::LineEntry> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBLineEntry_h_ diff --git a/include/lldb/API/SBListener.h b/include/lldb/API/SBListener.h new file mode 100644 index 0000000..c5a0473 --- /dev/null +++ b/include/lldb/API/SBListener.h @@ -0,0 +1,135 @@ +//===-- SBListener.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_SBListener_h_ +#define LLDB_SBListener_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBListener +{ +public: + SBListener (); + + SBListener (const char *name); + + SBListener (const SBListener &rhs); + + ~SBListener (); + + const lldb::SBListener & + operator = (const lldb::SBListener &rhs); + + void + AddEvent (const lldb::SBEvent &event); + + void + Clear (); + + bool + IsValid () const; + + uint32_t + StartListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask); + + bool + StopListeningForEventClass (SBDebugger &debugger, + const char *broadcaster_class, + uint32_t event_mask); + + uint32_t + StartListeningForEvents (const lldb::SBBroadcaster& broadcaster, + uint32_t event_mask); + + bool + StopListeningForEvents (const lldb::SBBroadcaster& broadcaster, + uint32_t event_mask); + + // Returns true if an event was recieved, false if we timed out. + bool + WaitForEvent (uint32_t num_seconds, + lldb::SBEvent &event); + + bool + WaitForEventForBroadcaster (uint32_t num_seconds, + const lldb::SBBroadcaster &broadcaster, + lldb::SBEvent &sb_event); + + bool + WaitForEventForBroadcasterWithType (uint32_t num_seconds, + const lldb::SBBroadcaster &broadcaster, + uint32_t event_type_mask, + lldb::SBEvent &sb_event); + + bool + PeekAtNextEvent (lldb::SBEvent &sb_event); + + bool + PeekAtNextEventForBroadcaster (const lldb::SBBroadcaster &broadcaster, + lldb::SBEvent &sb_event); + + bool + PeekAtNextEventForBroadcasterWithType (const lldb::SBBroadcaster &broadcaster, + uint32_t event_type_mask, + lldb::SBEvent &sb_event); + + bool + GetNextEvent (lldb::SBEvent &sb_event); + + bool + GetNextEventForBroadcaster (const lldb::SBBroadcaster &broadcaster, + lldb::SBEvent &sb_event); + + bool + GetNextEventForBroadcasterWithType (const lldb::SBBroadcaster &broadcaster, + uint32_t event_type_mask, + lldb::SBEvent &sb_event); + + bool + HandleBroadcastEvent (const lldb::SBEvent &event); + +protected: + friend class SBBroadcaster; + friend class SBCommandInterpreter; + friend class SBDebugger; + friend class SBTarget; + + SBListener (lldb_private::Listener &listener); + +private: + + lldb_private::Listener * + operator->() const; + + lldb_private::Listener * + get() const; + + lldb_private::Listener & + ref() const; + + lldb_private::Listener & + operator *(); + + const lldb_private::Listener & + operator *() const; + + void + reset(lldb_private::Listener *listener, bool transfer_ownership); + + lldb::ListenerSP m_opaque_sp; + lldb_private::Listener *m_opaque_ptr; +}; + +} // namespace lldb + +#endif // LLDB_SBListener_h_ diff --git a/include/lldb/API/SBModule.h b/include/lldb/API/SBModule.h new file mode 100644 index 0000000..a3c4879 --- /dev/null +++ b/include/lldb/API/SBModule.h @@ -0,0 +1,287 @@ +//===-- SBModule.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_SBModule_h_ +#define LLDB_SBModule_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBSection.h" +#include "lldb/API/SBSymbolContext.h" +#include "lldb/API/SBValueList.h" + +namespace lldb { + +class SBModule +{ +public: + + SBModule (); + + SBModule (const SBModule &rhs); + + SBModule (const SBModuleSpec &module_spec); + + const SBModule & + operator = (const SBModule &rhs); + + SBModule (lldb::SBProcess &process, + lldb::addr_t header_addr); + + ~SBModule (); + + bool + IsValid () const; + + void + Clear(); + + //------------------------------------------------------------------ + /// 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. + //------------------------------------------------------------------ + lldb::SBFileSpec + GetFileSpec () const; + + //------------------------------------------------------------------ + /// 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. + //------------------------------------------------------------------ + lldb::SBFileSpec + GetPlatformFileSpec () const; + + bool + SetPlatformFileSpec (const lldb::SBFileSpec &platform_file); + + lldb::ByteOrder + GetByteOrder (); + + uint32_t + GetAddressByteSize(); + + const char * + GetTriple (); + + const uint8_t * + GetUUIDBytes () const; + + const char * + GetUUIDString () const; + + bool + operator == (const lldb::SBModule &rhs) const; + + bool + operator != (const lldb::SBModule &rhs) const; + + lldb::SBSection + FindSection (const char *sect_name); + + lldb::SBAddress + ResolveFileAddress (lldb::addr_t vm_addr); + + lldb::SBSymbolContext + ResolveSymbolContextForAddress (const lldb::SBAddress& addr, + uint32_t resolve_scope); + + bool + GetDescription (lldb::SBStream &description); + + uint32_t + GetNumCompileUnits(); + + lldb::SBCompileUnit + GetCompileUnitAtIndex (uint32_t); + + size_t + GetNumSymbols (); + + lldb::SBSymbol + GetSymbolAtIndex (size_t idx); + + lldb::SBSymbol + FindSymbol (const char *name, + lldb::SymbolType type = eSymbolTypeAny); + + lldb::SBSymbolContextList + FindSymbols (const char *name, + lldb::SymbolType type = eSymbolTypeAny); + + size_t + GetNumSections (); + + lldb::SBSection + GetSectionAtIndex (size_t idx); + //------------------------------------------------------------------ + /// 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. + /// + /// @return + /// A lldb::SBSymbolContextList that gets filled in with all of + /// the symbol contexts for all the matches. + //------------------------------------------------------------------ + lldb::SBSymbolContextList + FindFunctions (const char *name, + uint32_t name_type_mask = lldb::eFunctionNameTypeAny); + + //------------------------------------------------------------------ + /// Find global and static variables by name. + /// + /// @param[in] target + /// A valid SBTarget instance representing the debuggee. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a max_matches. + /// + /// @return + /// A list of matched variables in an SBValueList. + //------------------------------------------------------------------ + lldb::SBValueList + FindGlobalVariables (lldb::SBTarget &target, + const char *name, + uint32_t max_matches); + + //------------------------------------------------------------------ + /// Find the first global (or static) variable by name. + /// + /// @param[in] target + /// A valid SBTarget instance representing the debuggee. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @return + /// An SBValue that gets filled in with the found variable (if any). + //------------------------------------------------------------------ + lldb::SBValue + FindFirstGlobalVariable (lldb::SBTarget &target, const char *name); + + lldb::SBType + FindFirstType (const char* name); + + lldb::SBTypeList + FindTypes (const char* type); + + lldb::SBType + GetBasicType(lldb::BasicType type); + + //------------------------------------------------------------------ + /// Get all types matching \a type_mask from debug info in this + /// module. + /// + /// @param[in] type_mask + /// A bitfield that consists of one or more bits logically OR'ed + /// together from the lldb::TypeClass enumeration. This allows + /// you to request only structure types, or only class, struct + /// and union types. Passing in lldb::eTypeClassAny will return + /// all types found in the debug information for this module. + /// + /// @return + /// A list of types in this module that match \a type_mask + //------------------------------------------------------------------ + lldb::SBTypeList + GetTypes (uint32_t type_mask = lldb::eTypeClassAny); + + //------------------------------------------------------------------ + /// Get the module version numbers. + /// + /// Many object files have a set of version numbers that describe + /// the version of the executable or shared library. Typically there + /// are major, minor and build, but there may be more. This function + /// will extract the versions from object files if they are available. + /// + /// If \a versions is NULL, or if \a num_versions is 0, the return + /// value will indicate how many version numbers are available in + /// this object file. Then a subsequent call can be made to this + /// function with a value of \a versions and \a num_versions that + /// has enough storage to store some or all version numbers. + /// + /// @param[out] versions + /// A pointer to an array of uint32_t types that is \a num_versions + /// long. If this value is NULL, the return value will indicate + /// how many version numbers are required for a subsequent call + /// to this function so that all versions can be retrieved. If + /// the value is non-NULL, then at most \a num_versions of the + /// existing versions numbers will be filled into \a versions. + /// If there is no version information available, \a versions + /// will be filled with \a num_versions UINT32_MAX values + /// and zero will be returned. + /// + /// @param[in] num_versions + /// The maximum number of entries to fill into \a versions. If + /// this value is zero, then the return value will indicate + /// how many version numbers there are in total so another call + /// to this function can be make with adequate storage in + /// \a versions to get all of the version numbers. If \a + /// num_versions is less than the actual number of version + /// numbers in this object file, only \a num_versions will be + /// filled into \a versions (if \a versions is non-NULL). + /// + /// @return + /// This function always returns the number of version numbers + /// that this object file has regardless of the number of + /// version numbers that were copied into \a versions. + //------------------------------------------------------------------ + uint32_t + GetVersion (uint32_t *versions, + uint32_t num_versions); + +private: + friend class SBAddress; + friend class SBFrame; + friend class SBSection; + friend class SBSymbolContext; + friend class SBTarget; + + explicit SBModule (const lldb::ModuleSP& module_sp); + + ModuleSP + GetSP () const; + + void + SetSP (const ModuleSP &module_sp); + + lldb::ModuleSP m_opaque_sp; +}; + + +} // namespace lldb + +#endif // LLDB_SBModule_h_ diff --git a/include/lldb/API/SBModuleSpec.h b/include/lldb/API/SBModuleSpec.h new file mode 100644 index 0000000..a615e01 --- /dev/null +++ b/include/lldb/API/SBModuleSpec.h @@ -0,0 +1,154 @@ +//===-- SBModuleSpec.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_SBModuleSpec_h_ +#define LLDB_SBModuleSpec_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBFileSpec.h" + +namespace lldb { + +class SBModuleSpec +{ +public: + + SBModuleSpec (); + + SBModuleSpec (const SBModuleSpec &rhs); + + ~SBModuleSpec (); + + const SBModuleSpec & + operator = (const SBModuleSpec &rhs); + + bool + IsValid () const; + + void + Clear(); + + //------------------------------------------------------------------ + /// Get const accessor for the module file. + /// + /// 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. + //------------------------------------------------------------------ + lldb::SBFileSpec + GetFileSpec (); + + void + SetFileSpec (const lldb::SBFileSpec &fspec); + + //------------------------------------------------------------------ + /// Get accessor for the module platform file. + /// + /// 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. + //------------------------------------------------------------------ + lldb::SBFileSpec + GetPlatformFileSpec (); + + void + SetPlatformFileSpec (const lldb::SBFileSpec &fspec); + + lldb::SBFileSpec + GetSymbolFileSpec (); + + void + SetSymbolFileSpec (const lldb::SBFileSpec &fspec); + + const char * + GetObjectName (); + + void + SetObjectName (const char *name); + + const char * + GetTriple (); + + void + SetTriple (const char *triple); + + const uint8_t * + GetUUIDBytes (); + + size_t + GetUUIDLength (); + + bool + SetUUIDBytes (const uint8_t *uuid, size_t uuid_len); + + bool + GetDescription (lldb::SBStream &description); + +private: + friend class SBModuleSpecList; + friend class SBModule; + friend class SBTarget; + + std::unique_ptr<lldb_private::ModuleSpec> m_opaque_ap; +}; + +class SBModuleSpecList +{ +public: + SBModuleSpecList(); + + SBModuleSpecList (const SBModuleSpecList &rhs); + + ~SBModuleSpecList(); + + SBModuleSpecList & + operator = (const SBModuleSpecList &rhs); + + static SBModuleSpecList + GetModuleSpecifications (const char *path); + + void + Append (const SBModuleSpec &spec); + + void + Append (const SBModuleSpecList &spec_list); + + SBModuleSpec + FindFirstMatchingSpec (const SBModuleSpec &match_spec); + + SBModuleSpecList + FindMatchingSpecs (const SBModuleSpec &match_spec); + + size_t + GetSize(); + + SBModuleSpec + GetSpecAtIndex (size_t i); + + bool + GetDescription (lldb::SBStream &description); + +private: + std::unique_ptr<lldb_private::ModuleSpecList> m_opaque_ap; +}; + +} // namespace lldb + +#endif // LLDB_SBModuleSpec_h_ diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h new file mode 100644 index 0000000..784f362 --- /dev/null +++ b/include/lldb/API/SBProcess.h @@ -0,0 +1,295 @@ +//===-- SBProcess.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_SBProcess_h_ +#define LLDB_SBProcess_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBError.h" +#include "lldb/API/SBTarget.h" +#include <stdio.h> + +namespace lldb { + +class SBEvent; + +class SBProcess +{ +public: + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + enum + { + eBroadcastBitStateChanged = (1 << 0), + eBroadcastBitInterrupt = (1 << 1), + eBroadcastBitSTDOUT = (1 << 2), + eBroadcastBitSTDERR = (1 << 3), + eBroadcastBitProfileData = (1 << 4) + }; + + SBProcess (); + + SBProcess (const lldb::SBProcess& rhs); + + const lldb::SBProcess& + operator = (const lldb::SBProcess& rhs); + + SBProcess (const lldb::ProcessSP &process_sp); + + ~SBProcess(); + + static const char * + GetBroadcasterClassName (); + + const char * + GetPluginName (); + + // DEPRECATED: use GetPluginName() + const char * + GetShortPluginName (); + + void + Clear (); + + bool + IsValid() const; + + lldb::SBTarget + GetTarget() const; + + lldb::ByteOrder + GetByteOrder() const; + + size_t + PutSTDIN (const char *src, size_t src_len); + + size_t + GetSTDOUT (char *dst, size_t dst_len) const; + + size_t + GetSTDERR (char *dst, size_t dst_len) const; + + size_t + GetAsyncProfileData(char *dst, size_t dst_len) const; + + void + ReportEventState (const lldb::SBEvent &event, FILE *out) const; + + void + AppendEventStateReport (const lldb::SBEvent &event, lldb::SBCommandReturnObject &result); + + //------------------------------------------------------------------ + /// 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. + //------------------------------------------------------------------ + bool + RemoteAttachToProcessWithID (lldb::pid_t pid, + lldb::SBError& error); + + bool + RemoteLaunch (char const **argv, + char const **envp, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + const char *working_directory, + uint32_t launch_flags, + bool stop_at_entry, + lldb::SBError& error); + + //------------------------------------------------------------------ + // Thread related functions + //------------------------------------------------------------------ + uint32_t + GetNumThreads (); + + lldb::SBThread + GetThreadAtIndex (size_t index); + + lldb::SBThread + GetThreadByID (lldb::tid_t sb_thread_id); + + lldb::SBThread + GetThreadByIndexID (uint32_t index_id); + + lldb::SBThread + GetSelectedThread () const; + + //------------------------------------------------------------------ + // Function for lazily creating a thread using the current OS + // plug-in. This function will be removed in the future when there + // are APIs to create SBThread objects through the interface and add + // them to the process through the SBProcess API. + //------------------------------------------------------------------ + lldb::SBThread + CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context); + + bool + SetSelectedThread (const lldb::SBThread &thread); + + bool + SetSelectedThreadByID (lldb::tid_t tid); + + bool + SetSelectedThreadByIndexID (uint32_t index_id); + + //------------------------------------------------------------------ + // Stepping related functions + //------------------------------------------------------------------ + + lldb::StateType + GetState (); + + int + GetExitStatus (); + + const char * + GetExitDescription (); + + //------------------------------------------------------------------ + /// Gets the process ID + /// + /// Returns the process identifier for the process as it is known + /// on the system on which the process is running. For unix systems + /// this is typically the same as if you called "getpid()" in the + /// process. + /// + /// @return + /// Returns LLDB_INVALID_PROCESS_ID if this object does not + /// contain a valid process object, or if the process has not + /// been launched. Returns a valid process ID if the process is + /// valid. + //------------------------------------------------------------------ + lldb::pid_t + GetProcessID (); + + //------------------------------------------------------------------ + /// Gets the unique ID associated with this process object + /// + /// Unique IDs start at 1 and increment up with each new process + /// instance. Since starting a process on a system might always + /// create a process with the same process ID, there needs to be a + /// way to tell two process instances apart. + /// + /// @return + /// Returns a non-zero integer ID if this object contains a + /// valid process object, zero if this object does not contain + /// a valid process object. + //------------------------------------------------------------------ + uint32_t + GetUniqueID(); + + uint32_t + GetAddressByteSize() const; + + lldb::SBError + Destroy (); + + lldb::SBError + Continue (); + + lldb::SBError + Stop (); + + lldb::SBError + Kill (); + + lldb::SBError + Detach (); + + lldb::SBError + Detach (bool keep_stopped); + + lldb::SBError + Signal (int signal); + + void + SendAsyncInterrupt(); + + uint32_t + GetStopID(bool include_expression_stops = false); + + size_t + ReadMemory (addr_t addr, void *buf, size_t size, lldb::SBError &error); + + size_t + WriteMemory (addr_t addr, const void *buf, size_t size, lldb::SBError &error); + + size_t + ReadCStringFromMemory (addr_t addr, void *buf, size_t size, lldb::SBError &error); + + uint64_t + ReadUnsignedFromMemory (addr_t addr, uint32_t byte_size, lldb::SBError &error); + + lldb::addr_t + ReadPointerFromMemory (addr_t addr, lldb::SBError &error); + + // Events + static lldb::StateType + GetStateFromEvent (const lldb::SBEvent &event); + + static bool + GetRestartedFromEvent (const lldb::SBEvent &event); + + static size_t + GetNumRestartedReasonsFromEvent (const lldb::SBEvent &event); + + static const char * + GetRestartedReasonAtIndexFromEvent (const lldb::SBEvent &event, size_t idx); + + static lldb::SBProcess + GetProcessFromEvent (const lldb::SBEvent &event); + + static bool + EventIsProcessEvent (const lldb::SBEvent &event); + + lldb::SBBroadcaster + GetBroadcaster () const; + + static const char * + GetBroadcasterClass (); + + bool + GetDescription (lldb::SBStream &description); + + uint32_t + GetNumSupportedHardwareWatchpoints (lldb::SBError &error) const; + + uint32_t + LoadImage (lldb::SBFileSpec &image_spec, lldb::SBError &error); + + lldb::SBError + UnloadImage (uint32_t image_token); + +protected: + friend class SBAddress; + friend class SBBreakpoint; + friend class SBBreakpointLocation; + friend class SBCommandInterpreter; + friend class SBDebugger; + friend class SBFunction; + friend class SBModule; + friend class SBTarget; + friend class SBThread; + friend class SBValue; + + lldb::ProcessSP + GetSP() const; + + void + SetSP (const lldb::ProcessSP &process_sp); + + lldb::ProcessWP m_opaque_wp; +}; + +} // namespace lldb + +#endif // LLDB_SBProcess_h_ diff --git a/include/lldb/API/SBSection.h b/include/lldb/API/SBSection.h new file mode 100644 index 0000000..3386484 --- /dev/null +++ b/include/lldb/API/SBSection.h @@ -0,0 +1,104 @@ +//===-- SBSection.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_SBSection_h_ +#define LLDB_SBSection_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBData.h" + +namespace lldb { + +class SBSection +{ +public: + + SBSection (); + + SBSection (const lldb::SBSection &rhs); + + ~SBSection (); + + const lldb::SBSection & + operator = (const lldb::SBSection &rhs); + + bool + IsValid () const; + + const char * + GetName (); + + lldb::SBSection + GetParent(); + + lldb::SBSection + FindSubSection (const char *sect_name); + + size_t + GetNumSubSections (); + + lldb::SBSection + GetSubSectionAtIndex (size_t idx); + + lldb::addr_t + GetFileAddress (); + + lldb::addr_t + GetLoadAddress (lldb::SBTarget &target); + + lldb::addr_t + GetByteSize (); + + uint64_t + GetFileOffset (); + + uint64_t + GetFileByteSize (); + + lldb::SBData + GetSectionData (); + + lldb::SBData + GetSectionData (uint64_t offset, + uint64_t size); + + SectionType + GetSectionType (); + + bool + operator == (const lldb::SBSection &rhs); + + bool + operator != (const lldb::SBSection &rhs); + + bool + GetDescription (lldb::SBStream &description); + + +private: + + friend class SBAddress; + friend class SBModule; + friend class SBTarget; + + SBSection (const lldb::SectionSP §ion_sp); + + lldb::SectionSP + GetSP() const; + + void + SetSP(const lldb::SectionSP §ion_sp); + + lldb::SectionWP m_opaque_wp; +}; + + +} // namespace lldb + +#endif // LLDB_SBSection_h_ diff --git a/include/lldb/API/SBSourceManager.h b/include/lldb/API/SBSourceManager.h new file mode 100644 index 0000000..5b52c49 --- /dev/null +++ b/include/lldb/API/SBSourceManager.h @@ -0,0 +1,53 @@ +//===-- SBSourceManager.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_SBSourceManager_h_ +#define LLDB_SBSourceManager_h_ + +#include "lldb/API/SBDefines.h" + +#include <stdio.h> + +namespace lldb { + +class SBSourceManager +{ +public: + SBSourceManager (const SBDebugger &debugger); + SBSourceManager (const SBTarget &target); + SBSourceManager (const SBSourceManager &rhs); + + ~SBSourceManager(); + + const lldb::SBSourceManager & + operator = (const lldb::SBSourceManager &rhs); + + size_t + DisplaySourceLinesWithLineNumbers (const lldb::SBFileSpec &file, + uint32_t line, + uint32_t context_before, + uint32_t context_after, + const char* current_line_cstr, + lldb::SBStream &s); + + +protected: + friend class SBCommandInterpreter; + friend class SBDebugger; + + SBSourceManager(lldb_private::SourceManager *source_manager); + +private: + + std::unique_ptr<lldb_private::SourceManagerImpl> m_opaque_ap; +}; + +} // namespace lldb + +#endif // LLDB_SBSourceManager_h_ diff --git a/include/lldb/API/SBStream.h b/include/lldb/API/SBStream.h new file mode 100644 index 0000000..038adf6 --- /dev/null +++ b/include/lldb/API/SBStream.h @@ -0,0 +1,111 @@ +//===-- SBStream.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_SBStream_h_ +#define LLDB_SBStream_h_ + +#include <stdio.h> + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBStream +{ +public: + + SBStream (); + + ~SBStream (); + + bool + IsValid() const; + + // If this stream is not redirected to a file, it will maintain a local + // cache for the stream data which can be accessed using this accessor. + const char * + GetData (); + + // If this stream is not redirected to a file, it will maintain a local + // cache for the stream output whose length can be accessed using this + // accessor. + size_t + GetSize(); + + void + Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + void + RedirectToFile (const char *path, bool append); + + void + RedirectToFileHandle (FILE *fh, bool transfer_fh_ownership); + + void + RedirectToFileDescriptor (int fd, bool transfer_fh_ownership); + + // If the stream is redirected to a file, forget about the file and if + // ownership of the file was transfered to this object, close the file. + // If the stream is backed by a local cache, clear this cache. + void + Clear (); + +protected: + friend class SBAddress; + friend class SBBlock; + friend class SBBreakpoint; + friend class SBBreakpointLocation; + friend class SBCommandReturnObject; + friend class SBCompileUnit; + friend class SBData; + friend class SBDebugger; + friend class SBDeclaration; + friend class SBEvent; + friend class SBFileSpec; + friend class SBFileSpecList; + friend class SBFrame; + friend class SBFunction; + friend class SBInstruction; + friend class SBInstructionList; + friend class SBLineEntry; + friend class SBModule; + friend class SBModuleSpec; + friend class SBModuleSpecList; + friend class SBProcess; + friend class SBSection; + friend class SBSourceManager; + friend class SBSymbol; + friend class SBSymbolContext; + friend class SBSymbolContextList; + friend class SBTarget; + friend class SBThread; + friend class SBType; + friend class SBTypeMember; + friend class SBValue; + friend class SBWatchpoint; + + lldb_private::Stream * + operator->(); + + lldb_private::Stream * + get(); + + lldb_private::Stream & + ref(); + +private: + + DISALLOW_COPY_AND_ASSIGN (SBStream); + std::unique_ptr<lldb_private::Stream> m_opaque_ap; + bool m_is_file; +}; + +} // namespace lldb + +#endif // LLDB_SBStream_h_ diff --git a/include/lldb/API/SBStringList.h b/include/lldb/API/SBStringList.h new file mode 100644 index 0000000..9d0be6e --- /dev/null +++ b/include/lldb/API/SBStringList.h @@ -0,0 +1,71 @@ +//===-- SBStringList.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_SBStringList_h_ +#define LLDB_SBStringList_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBStringList +{ +public: + + SBStringList (); + + SBStringList (const lldb::SBStringList &rhs); + + const SBStringList & + operator = (const SBStringList &rhs); + + ~SBStringList (); + + bool + IsValid() const; + + void + AppendString (const char *str); + + void + AppendList (const char **strv, int strc); + + void + AppendList (const lldb::SBStringList &strings); + + uint32_t + GetSize () const; + + const char * + GetStringAtIndex (size_t idx); + + void + Clear (); + +protected: + friend class SBCommandInterpreter; + friend class SBDebugger; + + SBStringList (const lldb_private::StringList *lldb_strings); + + const lldb_private::StringList * + operator->() const; + + const lldb_private::StringList & + operator*() const; + +private: + + std::unique_ptr<lldb_private::StringList> m_opaque_ap; + +}; + +} // namespace lldb + +#endif // LLDB_SBStringList_h_ diff --git a/include/lldb/API/SBSymbol.h b/include/lldb/API/SBSymbol.h new file mode 100644 index 0000000..0a528a9 --- /dev/null +++ b/include/lldb/API/SBSymbol.h @@ -0,0 +1,109 @@ +//===-- SBSymbol.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_SBSymbol_h_ +#define LLDB_SBSymbol_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBAddress.h" +#include "lldb/API/SBInstructionList.h" +#include "lldb/API/SBTarget.h" + +namespace lldb { + +class SBSymbol +{ +public: + + SBSymbol (); + + ~SBSymbol (); + + SBSymbol (const lldb::SBSymbol &rhs); + + const lldb::SBSymbol & + operator = (const lldb::SBSymbol &rhs); + + bool + IsValid () const; + + + const char * + GetName() const; + + const char * + GetMangledName () const; + + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target); + + lldb::SBInstructionList + GetInstructions (lldb::SBTarget target, const char *flavor_string); + + SBAddress + GetStartAddress (); + + SBAddress + GetEndAddress (); + + uint32_t + GetPrologueByteSize (); + + SymbolType + GetType (); + + bool + operator == (const lldb::SBSymbol &rhs) const; + + bool + operator != (const lldb::SBSymbol &rhs) const; + + bool + GetDescription (lldb::SBStream &description); + + //---------------------------------------------------------------------- + // Returns true if the symbol is externally visible in the module that + // it is defined in + //---------------------------------------------------------------------- + bool + IsExternal(); + + //---------------------------------------------------------------------- + // Returns true if the symbol was synthetically generated from something + // other than the actual symbol table itself in the object file. + //---------------------------------------------------------------------- + bool + IsSynthetic(); + +protected: + + lldb_private::Symbol * + get (); + + void + reset (lldb_private::Symbol *); + +private: + friend class SBAddress; + friend class SBFrame; + friend class SBModule; + friend class SBSymbolContext; + + SBSymbol (lldb_private::Symbol *lldb_object_ptr); + + void + SetSymbol (lldb_private::Symbol *lldb_object_ptr); + + lldb_private::Symbol *m_opaque_ptr; +}; + + +} // namespace lldb + +#endif // LLDB_SBSymbol_h_ diff --git a/include/lldb/API/SBSymbolContext.h b/include/lldb/API/SBSymbolContext.h new file mode 100644 index 0000000..fee2d19 --- /dev/null +++ b/include/lldb/API/SBSymbolContext.h @@ -0,0 +1,94 @@ +//===-- SBSymbolContext.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_SBSymbolContext_h_ +#define LLDB_SBSymbolContext_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBBlock.h" +#include "lldb/API/SBCompileUnit.h" +#include "lldb/API/SBFunction.h" +#include "lldb/API/SBLineEntry.h" +#include "lldb/API/SBModule.h" +#include "lldb/API/SBSymbol.h" + +namespace lldb { + +class SBSymbolContext +{ +public: + SBSymbolContext (); + + SBSymbolContext (const lldb::SBSymbolContext& rhs); + + ~SBSymbolContext (); + + bool + IsValid () const; + + const lldb::SBSymbolContext & + operator = (const lldb::SBSymbolContext &rhs); + + lldb::SBModule GetModule (); + lldb::SBCompileUnit GetCompileUnit (); + lldb::SBFunction GetFunction (); + lldb::SBBlock GetBlock (); + lldb::SBLineEntry GetLineEntry (); + lldb::SBSymbol GetSymbol (); + + void SetModule (lldb::SBModule module); + void SetCompileUnit (lldb::SBCompileUnit compile_unit); + void SetFunction (lldb::SBFunction function); + void SetBlock (lldb::SBBlock block); + void SetLineEntry (lldb::SBLineEntry line_entry); + void SetSymbol (lldb::SBSymbol symbol); + + SBSymbolContext + GetParentOfInlinedScope (const SBAddress &curr_frame_pc, + SBAddress &parent_frame_addr) const; + + bool + GetDescription (lldb::SBStream &description); + +protected: + friend class SBAddress; + friend class SBFrame; + friend class SBModule; + friend class SBThread; + friend class SBTarget; + friend class SBSymbolContextList; + + lldb_private::SymbolContext* + operator->() const; + + lldb_private::SymbolContext& + operator*(); + + lldb_private::SymbolContext& + ref(); + + const lldb_private::SymbolContext& + operator*() const; + + lldb_private::SymbolContext * + get() const; + + SBSymbolContext (const lldb_private::SymbolContext *sc_ptr); + + void + SetSymbolContext (const lldb_private::SymbolContext *sc_ptr); + +private: + std::unique_ptr<lldb_private::SymbolContext> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBSymbolContext_h_ diff --git a/include/lldb/API/SBSymbolContextList.h b/include/lldb/API/SBSymbolContextList.h new file mode 100644 index 0000000..6cc78e4 --- /dev/null +++ b/include/lldb/API/SBSymbolContextList.h @@ -0,0 +1,69 @@ +//===-- SBSymbolContextList.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_SBSymbolContextList_h_ +#define LLDB_SBSymbolContextList_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBSymbolContext.h" + +namespace lldb { + +class SBSymbolContextList +{ +public: + SBSymbolContextList (); + + SBSymbolContextList (const lldb::SBSymbolContextList& rhs); + + ~SBSymbolContextList (); + + const lldb::SBSymbolContextList & + operator = (const lldb::SBSymbolContextList &rhs); + + bool + IsValid () const; + + uint32_t + GetSize() const; + + lldb::SBSymbolContext + GetContextAtIndex (uint32_t idx); + + bool + GetDescription (lldb::SBStream &description); + + void + Append (lldb::SBSymbolContext &sc); + + void + Append (lldb::SBSymbolContextList &sc_list); + + void + Clear(); + +protected: + + friend class SBModule; + friend class SBTarget; + + lldb_private::SymbolContextList* + operator->() const; + + lldb_private::SymbolContextList& + operator*() const; + +private: + std::unique_ptr<lldb_private::SymbolContextList> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBSymbolContextList_h_ diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h new file mode 100644 index 0000000..15aeed4 --- /dev/null +++ b/include/lldb/API/SBTarget.h @@ -0,0 +1,828 @@ +//===-- SBTarget.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_SBTarget_h_ +#define LLDB_SBTarget_h_ + +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBAddress.h" +#include "lldb/API/SBBroadcaster.h" +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBFileSpecList.h" +#include "lldb/API/SBSymbolContextList.h" +#include "lldb/API/SBType.h" +#include "lldb/API/SBValue.h" +#include "lldb/API/SBWatchpoint.h" + +namespace lldb { + +class SBLaunchInfo +{ +public: + SBLaunchInfo (const char **argv); + + ~SBLaunchInfo(); + + uint32_t + GetUserID(); + + uint32_t + GetGroupID(); + + bool + UserIDIsValid (); + + bool + GroupIDIsValid (); + + void + SetUserID (uint32_t uid); + + void + SetGroupID (uint32_t gid); + + uint32_t + GetNumArguments (); + + const char * + GetArgumentAtIndex (uint32_t idx); + + void + SetArguments (const char **argv, bool append); + + uint32_t + GetNumEnvironmentEntries (); + + const char * + GetEnvironmentEntryAtIndex (uint32_t idx); + + void + SetEnvironmentEntries (const char **envp, bool append); + + void + Clear (); + + const char * + GetWorkingDirectory () const; + + void + SetWorkingDirectory (const char *working_dir); + + uint32_t + GetLaunchFlags (); + + void + SetLaunchFlags (uint32_t flags); + + const char * + GetProcessPluginName (); + + void + SetProcessPluginName (const char *plugin_name); + + const char * + GetShell (); + + void + SetShell (const char * path); + + uint32_t + GetResumeCount (); + + void + SetResumeCount (uint32_t c); + + bool + AddCloseFileAction (int fd); + + bool + AddDuplicateFileAction (int fd, int dup_fd); + + bool + AddOpenFileAction (int fd, const char *path, bool read, bool write); + + bool + AddSuppressFileAction (int fd, bool read, bool write); + +protected: + friend class SBTarget; + + lldb_private::ProcessLaunchInfo & + ref (); + + ProcessLaunchInfoSP m_opaque_sp; +}; + +class SBAttachInfo +{ +public: + SBAttachInfo (); + + SBAttachInfo (lldb::pid_t pid); + + SBAttachInfo (const char *path, bool wait_for); + + SBAttachInfo (const SBAttachInfo &rhs); + + ~SBAttachInfo(); + + SBAttachInfo & + operator = (const SBAttachInfo &rhs); + + lldb::pid_t + GetProcessID (); + + void + SetProcessID (lldb::pid_t pid); + + void + SetExecutable (const char *path); + + void + SetExecutable (lldb::SBFileSpec exe_file); + + bool + GetWaitForLaunch (); + + void + SetWaitForLaunch (bool b); + + bool + GetIgnoreExisting (); + + void + SetIgnoreExisting (bool b); + + uint32_t + GetResumeCount (); + + void + SetResumeCount (uint32_t c); + + const char * + GetProcessPluginName (); + + void + SetProcessPluginName (const char *plugin_name); + + uint32_t + GetUserID(); + + uint32_t + GetGroupID(); + + bool + UserIDIsValid (); + + bool + GroupIDIsValid (); + + void + SetUserID (uint32_t uid); + + void + SetGroupID (uint32_t gid); + + uint32_t + GetEffectiveUserID(); + + uint32_t + GetEffectiveGroupID(); + + bool + EffectiveUserIDIsValid (); + + bool + EffectiveGroupIDIsValid (); + + void + SetEffectiveUserID (uint32_t uid); + + void + SetEffectiveGroupID (uint32_t gid); + + lldb::pid_t + GetParentProcessID (); + + void + SetParentProcessID (lldb::pid_t pid); + + bool + ParentProcessIDIsValid(); + + +protected: + friend class SBTarget; + + lldb_private::ProcessAttachInfo & + ref (); + + ProcessAttachInfoSP m_opaque_sp; +}; + +class SBTarget +{ +public: + //------------------------------------------------------------------ + // Broadcaster bits. + //------------------------------------------------------------------ + enum + { + eBroadcastBitBreakpointChanged = (1 << 0), + eBroadcastBitModulesLoaded = (1 << 1), + eBroadcastBitModulesUnloaded = (1 << 2), + eBroadcastBitWatchpointChanged = (1 << 3), + eBroadcastBitSymbolsLoaded = (1 << 4) + }; + + //------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------ + SBTarget (); + + SBTarget (const lldb::SBTarget& rhs); + + SBTarget (const lldb::TargetSP& target_sp); + + const lldb::SBTarget& + operator = (const lldb::SBTarget& rhs); + + //------------------------------------------------------------------ + // Destructor + //------------------------------------------------------------------ + ~SBTarget(); + + bool + IsValid() const; + + static const char * + GetBroadcasterClassName (); + + lldb::SBProcess + GetProcess (); + + //------------------------------------------------------------------ + /// Launch a new process. + /// + /// Launch a new process by spawning a new process using the + /// target object's executable module's file as the file to launch. + /// Arguments are given in \a argv, and the environment variables + /// are in \a envp. Standard input and output files can be + /// optionally re-directed to \a stdin_path, \a stdout_path, and + /// \a stderr_path. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] argv + /// The argument array. + /// + /// @param[in] envp + /// The environment array. + /// + /// @param[in] launch_flags + /// Flags to modify the launch (@see lldb::LaunchFlags) + /// + /// @param[in] stdin_path + /// The path to use when re-directing the STDIN of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stdout_path + /// The path to use when re-directing the STDOUT of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stderr_path + /// The path to use when re-directing the STDERR of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] working_directory + /// The working directory to have the child process run in + /// + /// @param[in] launch_flags + /// Some launch options specified by logical OR'ing + /// lldb::LaunchFlags enumeration values together. + /// + /// @param[in] stop_at_endtry + /// If false do not stop the inferior at the entry point. + /// + /// @param[out] + /// An error object. Contains the reason if there is some failure. + /// + /// @return + /// A process object for the newly created process. + //------------------------------------------------------------------ + lldb::SBProcess + Launch (SBListener &listener, + char const **argv, + char const **envp, + const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + const char *working_directory, + uint32_t launch_flags, // See LaunchFlags + bool stop_at_entry, + lldb::SBError& error); + + + //------------------------------------------------------------------ + /// Launch a new process with sensible defaults. + /// + /// @param[in] argv + /// The argument array. + /// + /// @param[in] envp + /// The environment array. + /// + /// @param[in] working_directory + /// The working directory to have the child process run in + /// + /// Default: listener + /// Set to the target's debugger (SBTarget::GetDebugger()) + /// + /// Default: launch_flags + /// Empty launch flags + /// + /// Default: stdin_path + /// Default: stdout_path + /// Default: stderr_path + /// A pseudo terminal will be used. + /// + /// @return + /// A process object for the newly created process. + //------------------------------------------------------------------ + SBProcess + LaunchSimple (const char **argv, + const char **envp, + const char *working_directory); + + SBProcess + Launch (SBLaunchInfo &launch_info, SBError& error); + + SBProcess + LoadCore (const char *core_file); + + SBProcess + Attach (SBAttachInfo &attach_info, SBError& error); + + //------------------------------------------------------------------ + /// Attach to process with pid. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] pid + /// The process ID to attach to. + /// + /// @param[out] + /// An error explaining what went wrong if attach fails. + /// + /// @return + /// A process object for the attached process. + //------------------------------------------------------------------ + lldb::SBProcess + AttachToProcessWithID (SBListener &listener, + lldb::pid_t pid, + lldb::SBError& error); + +#if defined(__APPLE__) + // We need to keep this around for a build or two since Xcode links + // to the 32 bit version of this function. We will take it out soon. + lldb::SBProcess + AttachToProcessWithID (SBListener &listener, + ::pid_t pid, // 32 bit int process ID + lldb::SBError& error); // DEPRECATED +#endif + //------------------------------------------------------------------ + /// Attach to process with name. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] name + /// Basename of process to attach to. + /// + /// @param[in] wait_for + /// If true wait for a new instance of 'name' to be launched. + /// + /// @param[out] + /// An error explaining what went wrong if attach fails. + /// + /// @return + /// A process object for the attached process. + //------------------------------------------------------------------ + lldb::SBProcess + AttachToProcessWithName (SBListener &listener, + const char *name, + bool wait_for, + lldb::SBError& error); + + //------------------------------------------------------------------ + /// Connect to a remote debug server with url. + /// + /// @param[in] listener + /// An optional listener that will receive all process events. + /// If \a listener is valid then \a listener will listen to all + /// process events. If not valid, then this target's debugger + /// (SBTarget::GetDebugger()) will listen to all process events. + /// + /// @param[in] url + /// The url to connect to, e.g., 'connect://localhost:12345'. + /// + /// @param[in] plugin_name + /// The plugin name to be used; can be NULL. + /// + /// @param[out] + /// An error explaining what went wrong if the connect fails. + /// + /// @return + /// A process object for the connected process. + //------------------------------------------------------------------ + lldb::SBProcess + ConnectRemote (SBListener &listener, + const char *url, + const char *plugin_name, + SBError& error); + + lldb::SBFileSpec + GetExecutable (); + + bool + AddModule (lldb::SBModule &module); + + lldb::SBModule + AddModule (const char *path, + const char *triple, + const char *uuid); + + lldb::SBModule + AddModule (const char *path, + const char *triple, + const char *uuid_cstr, + const char *symfile); + + lldb::SBModule + AddModule (const SBModuleSpec &module_spec); + + uint32_t + GetNumModules () const; + + lldb::SBModule + GetModuleAtIndex (uint32_t idx); + + bool + RemoveModule (lldb::SBModule module); + + lldb::SBDebugger + GetDebugger() const; + + lldb::SBModule + FindModule (const lldb::SBFileSpec &file_spec); + + lldb::ByteOrder + GetByteOrder (); + + uint32_t + GetAddressByteSize(); + + const char * + GetTriple (); + + //------------------------------------------------------------------ + /// Set the base load address for a module section. + /// + /// @param[in] section + /// The section whose base load address will be set within this + /// target. + /// + /// @param[in] section_base_addr + /// The base address for the section. + /// + /// @return + /// An error to indicate success, fail, and any reason for + /// failure. + //------------------------------------------------------------------ + lldb::SBError + SetSectionLoadAddress (lldb::SBSection section, + lldb::addr_t section_base_addr); + + //------------------------------------------------------------------ + /// Clear the base load address for a module section. + /// + /// @param[in] section + /// The section whose base load address will be cleared within + /// this target. + /// + /// @return + /// An error to indicate success, fail, and any reason for + /// failure. + //------------------------------------------------------------------ + lldb::SBError + ClearSectionLoadAddress (lldb::SBSection section); + + //------------------------------------------------------------------ + /// Slide all file addresses for all module sections so that \a module + /// appears to loaded at these slide addresses. + /// + /// When you need all sections within a module to be loaded at a + /// rigid slide from the addresses found in the module object file, + /// this function will allow you to easily and quickly slide all + /// module sections. + /// + /// @param[in] module + /// The module to load. + /// + /// @param[in] sections_offset + /// An offset that will be applied to all section file addresses + /// (the virtual addresses found in the object file itself). + /// + /// @return + /// An error to indicate success, fail, and any reason for + /// failure. + //------------------------------------------------------------------ + lldb::SBError + SetModuleLoadAddress (lldb::SBModule module, + int64_t sections_offset); + + + //------------------------------------------------------------------ + /// The the section base load addresses for all sections in a module. + /// + /// @param[in] module + /// The module to unload. + /// + /// @return + /// An error to indicate success, fail, and any reason for + /// failure. + //------------------------------------------------------------------ + lldb::SBError + ClearModuleLoadAddress (lldb::SBModule module); + + //------------------------------------------------------------------ + /// 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. + /// + /// @return + /// A lldb::SBSymbolContextList that gets filled in with all of + /// the symbol contexts for all the matches. + //------------------------------------------------------------------ + lldb::SBSymbolContextList + FindFunctions (const char *name, + uint32_t name_type_mask = lldb::eFunctionNameTypeAny); + + //------------------------------------------------------------------ + /// Find global and static variables by name. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a max_matches. + /// + /// @return + /// A list of matched variables in an SBValueList. + //------------------------------------------------------------------ + lldb::SBValueList + FindGlobalVariables (const char *name, + uint32_t max_matches); + + //------------------------------------------------------------------ + /// Find the first global (or static) variable by name. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @return + /// An SBValue that gets filled in with the found variable (if any). + //------------------------------------------------------------------ + lldb::SBValue + FindFirstGlobalVariable (const char* name); + + void + Clear (); + + lldb::SBAddress + ResolveLoadAddress (lldb::addr_t vm_addr); + + SBSymbolContext + ResolveSymbolContextForAddress (const SBAddress& addr, + uint32_t resolve_scope); + + lldb::SBBreakpoint + BreakpointCreateByLocation (const char *file, uint32_t line); + + lldb::SBBreakpoint + BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line); + + lldb::SBBreakpoint + BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL); + + // This version uses name_type_mask = eFunctionNameTypeAuto + lldb::SBBreakpoint + BreakpointCreateByName (const char *symbol_name, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + + lldb::SBBreakpoint + BreakpointCreateByName (const char *symbol_name, + uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + + lldb::SBBreakpoint + BreakpointCreateByNames (const char *symbol_name[], + uint32_t num_names, + uint32_t name_type_mask, // Logical OR one or more FunctionNameType enum bits + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + + lldb::SBBreakpoint + BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = NULL); + + lldb::SBBreakpoint + BreakpointCreateByRegex (const char *symbol_name_regex, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + + lldb::SBBreakpoint + BreakpointCreateBySourceRegex (const char *source_regex, + const lldb::SBFileSpec &source_file, + const char *module_name = NULL); + + lldb::SBBreakpoint + BreakpointCreateBySourceRegex (const char *source_regex, + const SBFileSpecList &module_list, + const lldb::SBFileSpecList &source_file); + + lldb::SBBreakpoint + BreakpointCreateForException (lldb::LanguageType language, + bool catch_bp, + bool throw_bp); + + lldb::SBBreakpoint + BreakpointCreateByAddress (addr_t address); + + uint32_t + GetNumBreakpoints () const; + + lldb::SBBreakpoint + GetBreakpointAtIndex (uint32_t idx) const; + + bool + BreakpointDelete (break_id_t break_id); + + lldb::SBBreakpoint + FindBreakpointByID (break_id_t break_id); + + bool + EnableAllBreakpoints (); + + bool + DisableAllBreakpoints (); + + bool + DeleteAllBreakpoints (); + + uint32_t + GetNumWatchpoints () const; + + lldb::SBWatchpoint + GetWatchpointAtIndex (uint32_t idx) const; + + bool + DeleteWatchpoint (lldb::watch_id_t watch_id); + + lldb::SBWatchpoint + FindWatchpointByID (lldb::watch_id_t watch_id); + + lldb::SBWatchpoint + WatchAddress (lldb::addr_t addr, size_t size, bool read, bool write, SBError& error); + + bool + EnableAllWatchpoints (); + + bool + DisableAllWatchpoints (); + + bool + DeleteAllWatchpoints (); + + lldb::SBBroadcaster + GetBroadcaster () const; + + lldb::SBType + FindFirstType (const char* type); + + lldb::SBTypeList + FindTypes (const char* type); + + lldb::SBType + GetBasicType(lldb::BasicType type); + + SBSourceManager + GetSourceManager(); + + lldb::SBInstructionList + ReadInstructions (lldb::SBAddress base_addr, uint32_t count); + + lldb::SBInstructionList + ReadInstructions (lldb::SBAddress base_addr, uint32_t count, const char *flavor_string); + + lldb::SBInstructionList + GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size); + + // The "WithFlavor" is necessary to keep SWIG from getting confused about overloaded arguments when + // using the buf + size -> Python Object magic. + + lldb::SBInstructionList + GetInstructionsWithFlavor (lldb::SBAddress base_addr, const char *flavor_string, const void *buf, size_t size); + + lldb::SBInstructionList + GetInstructions (lldb::addr_t base_addr, const void *buf, size_t size); + + lldb::SBInstructionList + GetInstructionsWithFlavor (lldb::addr_t base_addr, const char *flavor_string, const void *buf, size_t size); + + lldb::SBSymbolContextList + FindSymbols (const char *name, + lldb::SymbolType type = eSymbolTypeAny); + + bool + operator == (const lldb::SBTarget &rhs) const; + + bool + operator != (const lldb::SBTarget &rhs) const; + + bool + GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level); + + lldb::SBValue + EvaluateExpression (const char *expr, const SBExpressionOptions &options); + + lldb::addr_t + GetStackRedZoneSize(); + +protected: + friend class SBAddress; + friend class SBBlock; + friend class SBDebugger; + friend class SBFunction; + friend class SBInstruction; + friend class SBModule; + friend class SBProcess; + friend class SBSection; + friend class SBSourceManager; + friend class SBSymbol; + friend class SBValue; + + //------------------------------------------------------------------ + // Constructors are private, use static Target::Create function to + // create an instance of this class. + //------------------------------------------------------------------ + + lldb::TargetSP + GetSP () const; + + void + SetSP (const lldb::TargetSP& target_sp); + + +private: + //------------------------------------------------------------------ + // For Target only + //------------------------------------------------------------------ + + lldb::TargetSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBTarget_h_ diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h new file mode 100644 index 0000000..9645f92 --- /dev/null +++ b/include/lldb/API/SBThread.h @@ -0,0 +1,220 @@ +//===-- SBThread.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_SBThread_h_ +#define LLDB_SBThread_h_ + +#include "lldb/API/SBDefines.h" + +#include <stdio.h> + +namespace lldb { + +class SBFrame; + +class SBThread +{ +public: + enum + { + eBroadcastBitStackChanged = (1 << 0), + eBroadcastBitThreadSuspended = (1 << 1), + eBroadcastBitThreadResumed = (1 << 2), + eBroadcastBitSelectedFrameChanged = (1 << 3), + eBroadcastBitThreadSelected = (1 << 4) + }; + + static const char * + GetBroadcasterClassName (); + + SBThread (); + + SBThread (const lldb::SBThread &thread); + + SBThread (const lldb::ThreadSP& lldb_object_sp); + + ~SBThread(); + + bool + IsValid() const; + + void + Clear (); + + lldb::StopReason + GetStopReason(); + + /// Get the number of words associated with the stop reason. + /// See also GetStopReasonDataAtIndex(). + size_t + GetStopReasonDataCount(); + + //-------------------------------------------------------------------------- + /// 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 1 watchpoint id + /// eStopReasonSignal 1 unix signal number + /// eStopReasonException N exception data + /// eStopReasonExec 0 + /// eStopReasonPlanComplete 0 + //-------------------------------------------------------------------------- + uint64_t + GetStopReasonDataAtIndex(uint32_t idx); + + size_t + GetStopDescription (char *dst, size_t dst_len); + + SBValue + GetStopReturnValue (); + + lldb::tid_t + GetThreadID () const; + + uint32_t + GetIndexID () const; + + const char * + GetName () const; + + const char * + GetQueueName() const; + + void + StepOver (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); + + void + StepInto (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); + + void + StepInto (const char *target_name, lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); + + void + StepOut (); + + void + StepOutOfFrame (lldb::SBFrame &frame); + + void + StepInstruction(bool step_over); + + SBError + StepOverUntil (lldb::SBFrame &frame, + lldb::SBFileSpec &file_spec, + uint32_t line); + + void + RunToAddress (lldb::addr_t addr); + + SBError + ReturnFromFrame (SBFrame &frame, SBValue &return_value); + + //-------------------------------------------------------------------------- + /// 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 not 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. + //-------------------------------------------------------------------------- + bool + Suspend(); + + bool + Resume (); + + bool + IsSuspended(); + + bool + IsStopped(); + + uint32_t + GetNumFrames (); + + lldb::SBFrame + GetFrameAtIndex (uint32_t idx); + + lldb::SBFrame + GetSelectedFrame (); + + lldb::SBFrame + SetSelectedFrame (uint32_t frame_idx); + + static bool + EventIsThreadEvent (const SBEvent &event); + + static SBFrame + GetStackFrameFromEvent (const SBEvent &event); + + static SBThread + GetThreadFromEvent (const SBEvent &event); + + lldb::SBProcess + GetProcess (); + + const lldb::SBThread & + operator = (const lldb::SBThread &rhs); + + bool + operator == (const lldb::SBThread &rhs) const; + + bool + operator != (const lldb::SBThread &rhs) const; + + bool + GetDescription (lldb::SBStream &description) const; + + bool + GetStatus (lldb::SBStream &status) const; + +protected: + friend class SBBreakpoint; + friend class SBBreakpointLocation; + friend class SBFrame; + friend class SBProcess; + friend class SBDebugger; + friend class SBValue; + + void + SetThread (const lldb::ThreadSP& lldb_object_sp); + +#ifndef SWIG + SBError + ResumeNewPlan (lldb_private::ExecutionContext &exe_ctx, lldb_private::ThreadPlan *new_plan); +#endif + +private: + lldb::ExecutionContextRefSP m_opaque_sp; +}; + +} // namespace lldb + +#endif // LLDB_SBThread_h_ diff --git a/include/lldb/API/SBType.h b/include/lldb/API/SBType.h new file mode 100644 index 0000000..3729b2f --- /dev/null +++ b/include/lldb/API/SBType.h @@ -0,0 +1,244 @@ +//===-- SBType.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_SBType_h_ +#define LLDB_SBType_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBTypeList; + +class SBTypeMember +{ +public: + SBTypeMember (); + + SBTypeMember (const lldb::SBTypeMember& rhs); + + ~SBTypeMember(); + + lldb::SBTypeMember& + operator = (const lldb::SBTypeMember& rhs); + + bool + IsValid() const; + + const char * + GetName (); + + lldb::SBType + GetType (); + + uint64_t + GetOffsetInBytes(); + + uint64_t + GetOffsetInBits(); + + bool + IsBitfield(); + + uint32_t + GetBitfieldSizeInBits(); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + +protected: + friend class SBType; + + void + reset (lldb_private::TypeMemberImpl *); + + lldb_private::TypeMemberImpl & + ref (); + + const lldb_private::TypeMemberImpl & + ref () const; + + std::unique_ptr<lldb_private::TypeMemberImpl> m_opaque_ap; +}; + +class SBType +{ +public: + + SBType(); + + SBType (const lldb::SBType &rhs); + + ~SBType (); + + bool + IsValid() const; + + uint64_t + GetByteSize(); + + bool + IsPointerType(); + + bool + IsReferenceType(); + + bool + IsFunctionType (); + + bool + IsPolymorphicClass (); + + lldb::SBType + GetPointerType(); + + lldb::SBType + GetPointeeType(); + + lldb::SBType + GetReferenceType(); + + lldb::SBType + GetDereferencedType(); + + lldb::SBType + GetUnqualifiedType(); + + lldb::SBType + GetCanonicalType(); + // Get the "lldb::BasicType" enumeration for a type. If a type is not a basic + // type eBasicTypeInvalid will be returned + lldb::BasicType + GetBasicType(); + + // The call below confusing and should really be renamed to "CreateBasicType" + lldb::SBType + GetBasicType(lldb::BasicType type); + + uint32_t + GetNumberOfFields (); + + uint32_t + GetNumberOfDirectBaseClasses (); + + uint32_t + GetNumberOfVirtualBaseClasses (); + + lldb::SBTypeMember + GetFieldAtIndex (uint32_t idx); + + lldb::SBTypeMember + GetDirectBaseClassAtIndex (uint32_t idx); + + lldb::SBTypeMember + GetVirtualBaseClassAtIndex (uint32_t idx); + + uint32_t + GetNumberOfTemplateArguments (); + + lldb::SBType + GetTemplateArgumentType (uint32_t idx); + + lldb::TemplateArgumentKind + GetTemplateArgumentKind (uint32_t idx); + + lldb::SBType + GetFunctionReturnType (); + + lldb::SBTypeList + GetFunctionArgumentTypes (); + + const char* + GetName(); + + lldb::TypeClass + GetTypeClass (); + + bool + IsTypeComplete (); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + + lldb::SBType & + operator = (const lldb::SBType &rhs); + + bool + operator == (lldb::SBType &rhs); + + bool + operator != (lldb::SBType &rhs); + +protected: + + lldb_private::TypeImpl & + ref (); + + const lldb_private::TypeImpl & + ref () const; + + lldb::TypeImplSP + GetSP (); + + void + SetSP (const lldb::TypeImplSP &type_impl_sp); + + lldb::TypeImplSP m_opaque_sp; + + friend class SBFunction; + friend class SBModule; + friend class SBTarget; + friend class SBTypeNameSpecifier; + friend class SBTypeMember; + friend class SBTypeList; + friend class SBValue; + + SBType (const lldb_private::ClangASTType &); + SBType (const lldb::TypeSP &); + SBType (const lldb::TypeImplSP &); + +}; + +class SBTypeList +{ +public: + SBTypeList(); + + SBTypeList(const lldb::SBTypeList& rhs); + + ~SBTypeList(); + + lldb::SBTypeList& + operator = (const lldb::SBTypeList& rhs); + + bool + IsValid(); + + void + Append (lldb::SBType type); + + lldb::SBType + GetTypeAtIndex (uint32_t index); + + uint32_t + GetSize(); + + +private: + std::unique_ptr<lldb_private::TypeListImpl> m_opaque_ap; + friend class SBModule; + friend class SBCompileUnit; +}; + + +} // namespace lldb + +#endif // LLDB_SBType_h_ diff --git a/include/lldb/API/SBTypeCategory.h b/include/lldb/API/SBTypeCategory.h new file mode 100644 index 0000000..f123e93 --- /dev/null +++ b/include/lldb/API/SBTypeCategory.h @@ -0,0 +1,168 @@ +//===-- SBTypeCategory.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_SBTypeCategory_h_ +#define LLDB_SBTypeCategory_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + + class SBTypeCategory + { + public: + + SBTypeCategory(); + + SBTypeCategory (const lldb::SBTypeCategory &rhs); + + ~SBTypeCategory (); + + bool + IsValid() const; + + bool + GetEnabled (); + + void + SetEnabled (bool); + + const char* + GetName(); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + + uint32_t + GetNumFormats (); + + uint32_t + GetNumSummaries (); + + uint32_t + GetNumFilters (); + +#ifndef LLDB_DISABLE_PYTHON + uint32_t + GetNumSynthetics (); +#endif + + SBTypeNameSpecifier + GetTypeNameSpecifierForFilterAtIndex (uint32_t); + + SBTypeNameSpecifier + GetTypeNameSpecifierForFormatAtIndex (uint32_t); + + SBTypeNameSpecifier + GetTypeNameSpecifierForSummaryAtIndex (uint32_t); + +#ifndef LLDB_DISABLE_PYTHON + SBTypeNameSpecifier + GetTypeNameSpecifierForSyntheticAtIndex (uint32_t); +#endif + + SBTypeFilter + GetFilterForType (SBTypeNameSpecifier); + + SBTypeFormat + GetFormatForType (SBTypeNameSpecifier); + +#ifndef LLDB_DISABLE_PYTHON + SBTypeSummary + GetSummaryForType (SBTypeNameSpecifier); +#endif + +#ifndef LLDB_DISABLE_PYTHON + SBTypeSynthetic + GetSyntheticForType (SBTypeNameSpecifier); +#endif + +#ifndef LLDB_DISABLE_PYTHON + SBTypeFilter + GetFilterAtIndex (uint32_t); +#endif + + SBTypeFormat + GetFormatAtIndex (uint32_t); + +#ifndef LLDB_DISABLE_PYTHON + SBTypeSummary + GetSummaryAtIndex (uint32_t); +#endif + +#ifndef LLDB_DISABLE_PYTHON + SBTypeSynthetic + GetSyntheticAtIndex (uint32_t); +#endif + + bool + AddTypeFormat (SBTypeNameSpecifier, + SBTypeFormat); + + bool + DeleteTypeFormat (SBTypeNameSpecifier); + +#ifndef LLDB_DISABLE_PYTHON + bool + AddTypeSummary (SBTypeNameSpecifier, + SBTypeSummary); +#endif + + bool + DeleteTypeSummary (SBTypeNameSpecifier); + + bool + AddTypeFilter (SBTypeNameSpecifier, + SBTypeFilter); + + bool + DeleteTypeFilter (SBTypeNameSpecifier); + +#ifndef LLDB_DISABLE_PYTHON + bool + AddTypeSynthetic (SBTypeNameSpecifier, + SBTypeSynthetic); + + bool + DeleteTypeSynthetic (SBTypeNameSpecifier); +#endif + + lldb::SBTypeCategory & + operator = (const lldb::SBTypeCategory &rhs); + + bool + operator == (lldb::SBTypeCategory &rhs); + + bool + operator != (lldb::SBTypeCategory &rhs); + + protected: + friend class SBDebugger; + + lldb::TypeCategoryImplSP + GetSP (); + + void + SetSP (const lldb::TypeCategoryImplSP &typecategory_impl_sp); + + TypeCategoryImplSP m_opaque_sp; + + SBTypeCategory (const lldb::TypeCategoryImplSP &); + + SBTypeCategory (const char*); + + bool + IsDefaultCategory(); + + }; + +} // namespace lldb + +#endif // LLDB_SBTypeCategory_h_ diff --git a/include/lldb/API/SBTypeFilter.h b/include/lldb/API/SBTypeFilter.h new file mode 100644 index 0000000..0169549 --- /dev/null +++ b/include/lldb/API/SBTypeFilter.h @@ -0,0 +1,92 @@ +//===-- SBTypeFilter.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_SBTypeFilter_h_ +#define LLDB_SBTypeFilter_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + + class SBTypeFilter + { + public: + + SBTypeFilter(); + + SBTypeFilter (uint32_t options); // see lldb::eTypeOption values + + SBTypeFilter (const lldb::SBTypeFilter &rhs); + + ~SBTypeFilter (); + + bool + IsValid() const; + + uint32_t + GetNumberOfExpressionPaths (); + + const char* + GetExpressionPathAtIndex (uint32_t i); + + bool + ReplaceExpressionPathAtIndex (uint32_t i, const char* item); + + void + AppendExpressionPath (const char* item); + + void + Clear(); + + uint32_t + GetOptions(); + + void + SetOptions (uint32_t); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + + lldb::SBTypeFilter & + operator = (const lldb::SBTypeFilter &rhs); + + bool + IsEqualTo (lldb::SBTypeFilter &rhs); + + bool + operator == (lldb::SBTypeFilter &rhs); + + bool + operator != (lldb::SBTypeFilter &rhs); + + protected: + friend class SBDebugger; + friend class SBTypeCategory; + friend class SBValue; + + lldb::TypeFilterImplSP + GetSP (); + + void + SetSP (const lldb::TypeFilterImplSP &typefilter_impl_sp); + + lldb::TypeFilterImplSP m_opaque_sp; + + SBTypeFilter (const lldb::TypeFilterImplSP &); + + bool + CopyOnWrite_Impl(); + + }; + + +} // namespace lldb + +#endif // LLDB_SBTypeFilter_h_ diff --git a/include/lldb/API/SBTypeFormat.h b/include/lldb/API/SBTypeFormat.h new file mode 100644 index 0000000..cd6345f --- /dev/null +++ b/include/lldb/API/SBTypeFormat.h @@ -0,0 +1,84 @@ +//===-- SBTypeFormat.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_SBTypeFormat_h_ +#define LLDB_SBTypeFormat_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBTypeFormat +{ +public: + + SBTypeFormat(); + + SBTypeFormat (lldb::Format format, + uint32_t options = 0); // see lldb::eTypeOption values + + SBTypeFormat (const lldb::SBTypeFormat &rhs); + + ~SBTypeFormat (); + + bool + IsValid() const; + + lldb::Format + GetFormat (); + + uint32_t + GetOptions(); + + void + SetFormat (lldb::Format); + + void + SetOptions (uint32_t); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + + lldb::SBTypeFormat & + operator = (const lldb::SBTypeFormat &rhs); + + bool + IsEqualTo (lldb::SBTypeFormat &rhs); + + bool + operator == (lldb::SBTypeFormat &rhs); + + bool + operator != (lldb::SBTypeFormat &rhs); + +protected: + friend class SBDebugger; + friend class SBTypeCategory; + friend class SBValue; + + lldb::TypeFormatImplSP + GetSP (); + + void + SetSP (const lldb::TypeFormatImplSP &typeformat_impl_sp); + + lldb::TypeFormatImplSP m_opaque_sp; + + SBTypeFormat (const lldb::TypeFormatImplSP &); + + bool + CopyOnWrite_Impl(); + +}; + + +} // namespace lldb + +#endif // LLDB_SBTypeFormat_h_ diff --git a/include/lldb/API/SBTypeNameSpecifier.h b/include/lldb/API/SBTypeNameSpecifier.h new file mode 100644 index 0000000..19d1988 --- /dev/null +++ b/include/lldb/API/SBTypeNameSpecifier.h @@ -0,0 +1,77 @@ +//===-- SBTypeNameSpecifier.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_SBTypeNameSpecifier_h_ +#define LLDB_SBTypeNameSpecifier_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + + class SBTypeNameSpecifier + { + public: + + SBTypeNameSpecifier(); + + SBTypeNameSpecifier (const char* name, + bool is_regex = false); + + SBTypeNameSpecifier (SBType type); + + SBTypeNameSpecifier (const lldb::SBTypeNameSpecifier &rhs); + + ~SBTypeNameSpecifier (); + + bool + IsValid() const; + + const char* + GetName(); + + SBType + GetType (); + + bool + IsRegex(); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + + lldb::SBTypeNameSpecifier & + operator = (const lldb::SBTypeNameSpecifier &rhs); + + bool + IsEqualTo (lldb::SBTypeNameSpecifier &rhs); + + bool + operator == (lldb::SBTypeNameSpecifier &rhs); + + bool + operator != (lldb::SBTypeNameSpecifier &rhs); + + protected: + friend class SBDebugger; + friend class SBTypeCategory; + + lldb::TypeNameSpecifierImplSP + GetSP (); + + void + SetSP (const lldb::TypeNameSpecifierImplSP &type_namespec_sp); + + lldb::TypeNameSpecifierImplSP m_opaque_sp; + + SBTypeNameSpecifier (const lldb::TypeNameSpecifierImplSP &); + }; + +} // namespace lldb + +#endif // LLDB_SBTypeNameSpecifier_h_ diff --git a/include/lldb/API/SBTypeSummary.h b/include/lldb/API/SBTypeSummary.h new file mode 100644 index 0000000..67a8607 --- /dev/null +++ b/include/lldb/API/SBTypeSummary.h @@ -0,0 +1,115 @@ +//===-- SBTypeSummary.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_SBTypeSummary_h_ +#define LLDB_SBTypeSummary_h_ + +#include "lldb/API/SBDefines.h" + +#ifndef LLDB_DISABLE_PYTHON + +namespace lldb { + + class SBTypeSummary + { + public: + + SBTypeSummary(); + + static SBTypeSummary + CreateWithSummaryString (const char* data, + uint32_t options = 0); // see lldb::eTypeOption values + + static SBTypeSummary + CreateWithFunctionName (const char* data, + uint32_t options = 0); // see lldb::eTypeOption values + + static SBTypeSummary + CreateWithScriptCode (const char* data, + uint32_t options = 0); // see lldb::eTypeOption values + + SBTypeSummary (const lldb::SBTypeSummary &rhs); + + ~SBTypeSummary (); + + bool + IsValid() const; + + bool + IsFunctionCode(); + + bool + IsFunctionName(); + + bool + IsSummaryString(); + + const char* + GetData (); + + void + SetSummaryString (const char* data); + + void + SetFunctionName (const char* data); + + void + SetFunctionCode (const char* data); + + uint32_t + GetOptions (); + + void + SetOptions (uint32_t); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + + lldb::SBTypeSummary & + operator = (const lldb::SBTypeSummary &rhs); + + bool + IsEqualTo (lldb::SBTypeSummary &rhs); + + bool + operator == (lldb::SBTypeSummary &rhs); + + bool + operator != (lldb::SBTypeSummary &rhs); + + protected: + friend class SBDebugger; + friend class SBTypeCategory; + friend class SBValue; + + lldb::TypeSummaryImplSP + GetSP (); + + void + SetSP (const lldb::TypeSummaryImplSP &typefilter_impl_sp); + + lldb::TypeSummaryImplSP m_opaque_sp; + + SBTypeSummary (const lldb::TypeSummaryImplSP &); + + bool + CopyOnWrite_Impl(); + + bool + ChangeSummaryType (bool want_script); + + }; + + +} // namespace lldb + +#endif // LLDB_DISABLE_PYTHON + +#endif // LLDB_SBTypeSummary_h_ diff --git a/include/lldb/API/SBTypeSynthetic.h b/include/lldb/API/SBTypeSynthetic.h new file mode 100644 index 0000000..e77cbfe --- /dev/null +++ b/include/lldb/API/SBTypeSynthetic.h @@ -0,0 +1,102 @@ +//===-- SBTypeSynthetic.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_SBTypeSynthetic_h_ +#define LLDB_SBTypeSynthetic_h_ + +#include "lldb/API/SBDefines.h" + +#ifndef LLDB_DISABLE_PYTHON + +namespace lldb { + + class SBTypeSynthetic + { + public: + + SBTypeSynthetic(); + + static SBTypeSynthetic + CreateWithClassName (const char* data, + uint32_t options = 0); // see lldb::eTypeOption values + + static SBTypeSynthetic + CreateWithScriptCode (const char* data, + uint32_t options = 0); // see lldb::eTypeOption values + + SBTypeSynthetic (const lldb::SBTypeSynthetic &rhs); + + ~SBTypeSynthetic (); + + bool + IsValid() const; + + bool + IsClassCode(); + + bool + IsClassName(); + + const char* + GetData (); + + void + SetClassName (const char* data); + + void + SetClassCode (const char* data); + + uint32_t + GetOptions (); + + void + SetOptions (uint32_t); + + bool + GetDescription (lldb::SBStream &description, + lldb::DescriptionLevel description_level); + + lldb::SBTypeSynthetic & + operator = (const lldb::SBTypeSynthetic &rhs); + + bool + IsEqualTo (lldb::SBTypeSynthetic &rhs); + + bool + operator == (lldb::SBTypeSynthetic &rhs); + + bool + operator != (lldb::SBTypeSynthetic &rhs); + + protected: + friend class SBDebugger; + friend class SBTypeCategory; + friend class SBValue; + + lldb::ScriptedSyntheticChildrenSP + GetSP (); + + void + SetSP (const lldb::ScriptedSyntheticChildrenSP &typefilter_impl_sp); + + lldb::ScriptedSyntheticChildrenSP m_opaque_sp; + + SBTypeSynthetic (const lldb::ScriptedSyntheticChildrenSP &); + + bool + CopyOnWrite_Impl(); + + }; + + +} // namespace lldb + +#endif // LLDB_DISABLE_PYTHON + +#endif // LLDB_SBTypeSynthetic_h_ diff --git a/include/lldb/API/SBValue.h b/include/lldb/API/SBValue.h new file mode 100644 index 0000000..2b9a344 --- /dev/null +++ b/include/lldb/API/SBValue.h @@ -0,0 +1,488 @@ +//===-- SBValue.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_SBValue_h_ +#define LLDB_SBValue_h_ + +#include "lldb/API/SBData.h" +#include "lldb/API/SBDefines.h" +#include "lldb/API/SBType.h" + +class ValueImpl; +class ValueLocker; + +namespace lldb { + +class SBValue +{ +friend class ValueLocker; + +public: + SBValue (); + + SBValue (const lldb::SBValue &rhs); + + lldb::SBValue & + operator =(const lldb::SBValue &rhs); + + ~SBValue (); + + bool + IsValid(); + + void + Clear(); + + SBError + GetError(); + + lldb::user_id_t + GetID (); + + const char * + GetName(); + + const char * + GetTypeName (); + + size_t + GetByteSize (); + + bool + IsInScope (); + + lldb::Format + GetFormat (); + + void + SetFormat (lldb::Format format); + + const char * + GetValue (); + + int64_t + GetValueAsSigned (lldb::SBError& error, int64_t fail_value=0); + + uint64_t + GetValueAsUnsigned (lldb::SBError& error, uint64_t fail_value=0); + + int64_t + GetValueAsSigned(int64_t fail_value=0); + + uint64_t + GetValueAsUnsigned(uint64_t fail_value=0); + + ValueType + GetValueType (); + + bool + GetValueDidChange (); + + const char * + GetSummary (); + + const char * + GetObjectDescription (); + + lldb::SBValue + GetDynamicValue (lldb::DynamicValueType use_dynamic); + + lldb::SBValue + GetStaticValue (); + + lldb::SBValue + GetNonSyntheticValue (); + + lldb::DynamicValueType + GetPreferDynamicValue (); + + void + SetPreferDynamicValue (lldb::DynamicValueType use_dynamic); + + bool + GetPreferSyntheticValue (); + + void + SetPreferSyntheticValue (bool use_synthetic); + + bool + IsDynamic (); + + bool + IsSynthetic (); + + const char * + GetLocation (); + + // Deprecated - use the one that takes SBError& + bool + SetValueFromCString (const char *value_str); + + bool + SetValueFromCString (const char *value_str, lldb::SBError& error); + + lldb::SBTypeFormat + GetTypeFormat (); + +#ifndef LLDB_DISABLE_PYTHON + lldb::SBTypeSummary + GetTypeSummary (); +#endif + + lldb::SBTypeFilter + GetTypeFilter (); + +#ifndef LLDB_DISABLE_PYTHON + lldb::SBTypeSynthetic + GetTypeSynthetic (); +#endif + + lldb::SBValue + GetChildAtIndex (uint32_t idx); + + lldb::SBValue + CreateChildAtOffset (const char *name, uint32_t offset, lldb::SBType type); + + lldb::SBValue + Cast (lldb::SBType type); + + lldb::SBValue + CreateValueFromExpression (const char *name, const char* expression); + + lldb::SBValue + CreateValueFromExpression (const char *name, const char* expression, SBExpressionOptions &options); + + lldb::SBValue + CreateValueFromAddress (const char* name, + lldb::addr_t address, + lldb::SBType type); + + // this has no address! GetAddress() and GetLoadAddress() as well as AddressOf() + // on the return of this call all return invalid + lldb::SBValue + CreateValueFromData (const char* name, + lldb::SBData data, + lldb::SBType type); + + //------------------------------------------------------------------ + /// Get a child value by index from a value. + /// + /// Structs, unions, classes, arrays and and pointers have child + /// values that can be access by index. + /// + /// Structs and unions access child members using a zero based index + /// for each child member. For + /// + /// Classes reserve the first indexes for base classes that have + /// members (empty base classes are omitted), and all members of the + /// current class will then follow the base classes. + /// + /// Pointers differ depending on what they point to. If the pointer + /// points to a simple type, the child at index zero + /// is the only child value available, unless \a synthetic_allowed + /// is \b true, in which case the pointer will be used as an array + /// and can create 'synthetic' child values using positive or + /// negative indexes. If the pointer points to an aggregate type + /// (an array, class, union, struct), then the pointee is + /// transparently skipped and any children are going to be the indexes + /// of the child values within the aggregate type. For example if + /// we have a 'Point' type and we have a SBValue that contains a + /// pointer to a 'Point' type, then the child at index zero will be + /// the 'x' member, and the child at index 1 will be the 'y' member + /// (the child at index zero won't be a 'Point' instance). + /// + /// Arrays have a preset number of children that can be accessed by + /// index and will returns invalid child values for indexes that are + /// out of bounds unless the \a synthetic_allowed is \b true. In this + /// case the array can create 'synthetic' child values for indexes + /// that aren't in the array bounds using positive or negative + /// indexes. + /// + /// @param[in] idx + /// The index of the child value to get + /// + /// @param[in] use_dynamic + /// An enumeration that specifies wether to get dynamic values, + /// and also if the target can be run to figure out the dynamic + /// type of the child value. + /// + /// @param[in] synthetic_allowed + /// If \b true, then allow child values to be created by index + /// for pointers and arrays for indexes that normally wouldn't + /// be allowed. + /// + /// @return + /// A new SBValue object that represents the child member value. + //------------------------------------------------------------------ + lldb::SBValue + GetChildAtIndex (uint32_t idx, + lldb::DynamicValueType use_dynamic, + bool can_create_synthetic); + + // Matches children of this object only and will match base classes and + // member names if this is a clang typed object. + uint32_t + GetIndexOfChildWithName (const char *name); + + // Matches child members of this object and child members of any base + // classes. + lldb::SBValue + GetChildMemberWithName (const char *name); + + // Matches child members of this object and child members of any base + // classes. + lldb::SBValue + GetChildMemberWithName (const char *name, lldb::DynamicValueType use_dynamic); + + // Expands nested expressions like .a->b[0].c[1]->d + lldb::SBValue + GetValueForExpressionPath(const char* expr_path); + + lldb::SBValue + AddressOf(); + + lldb::addr_t + GetLoadAddress(); + + lldb::SBAddress + GetAddress(); + + //------------------------------------------------------------------ + /// Get an SBData wrapping what this SBValue points to. + /// + /// This method will dereference the current SBValue, if its + /// data type is a T* or T[], and extract item_count elements + /// of type T from it, copying their contents in an SBData. + /// + /// @param[in] item_idx + /// The index of the first item to retrieve. For an array + /// this is equivalent to array[item_idx], for a pointer + /// to *(pointer + item_idx). In either case, the measurement + /// unit for item_idx is the sizeof(T) rather than the byte + /// + /// @param[in] item_count + /// How many items should be copied into the output. By default + /// only one item is copied, but more can be asked for. + /// + /// @return + /// An SBData with the contents of the copied items, on success. + /// An empty SBData otherwise. + //------------------------------------------------------------------ + lldb::SBData + GetPointeeData (uint32_t item_idx = 0, + uint32_t item_count = 1); + + //------------------------------------------------------------------ + /// Get an SBData wrapping the contents of this SBValue. + /// + /// This method will read the contents of this object in memory + /// and copy them into an SBData for future use. + /// + /// @return + /// An SBData with the contents of this SBValue, on success. + /// An empty SBData otherwise. + //------------------------------------------------------------------ + lldb::SBData + GetData (); + + bool + SetData (lldb::SBData &data, lldb::SBError& error); + + lldb::SBDeclaration + GetDeclaration (); + + //------------------------------------------------------------------ + /// Find out if a SBValue might have children. + /// + /// This call is much more efficient than GetNumChildren() as it + /// doesn't need to complete the underlying type. This is designed + /// to be used in a UI environment in order to detect if the + /// disclosure triangle should be displayed or not. + /// + /// This function returns true for class, union, structure, + /// pointers, references, arrays and more. Again, it does so without + /// doing any expensive type completion. + /// + /// @return + /// Returns \b true if the SBValue might have children, or \b + /// false otherwise. + //------------------------------------------------------------------ + bool + MightHaveChildren (); + + uint32_t + GetNumChildren (); + + void * + GetOpaqueType(); + + lldb::SBTarget + GetTarget(); + + lldb::SBProcess + GetProcess(); + + lldb::SBThread + GetThread(); + + lldb::SBFrame + GetFrame(); + + lldb::SBValue + Dereference (); + + bool + TypeIsPointerType (); + + lldb::SBType + GetType(); + + bool + GetDescription (lldb::SBStream &description); + + bool + GetExpressionPath (lldb::SBStream &description); + + bool + GetExpressionPath (lldb::SBStream &description, + bool qualify_cxx_base_classes); + + SBValue (const lldb::ValueObjectSP &value_sp); + + //------------------------------------------------------------------ + /// Watch this value if it resides in memory. + /// + /// Sets a watchpoint on the value. + /// + /// @param[in] resolve_location + /// Resolve the location of this value once and watch its address. + /// This value must currently be set to \b true as watching all + /// locations of a variable or a variable path is not yet supported, + /// though we plan to support it in the future. + /// + /// @param[in] read + /// Stop when this value is accessed. + /// + /// @param[in] write + /// Stop when this value is modified + /// + /// @param[out] + /// An error object. Contains the reason if there is some failure. + /// + /// @return + /// An SBWatchpoint object. This object might not be valid upon + /// return due to a value not being contained in memory, too + /// large, or watchpoint resources are not available or all in + /// use. + //------------------------------------------------------------------ + lldb::SBWatchpoint + Watch (bool resolve_location, bool read, bool write, SBError &error); + + // Backward compatibility fix in the interim. + lldb::SBWatchpoint + Watch (bool resolve_location, bool read, bool write); + + //------------------------------------------------------------------ + /// Watch this value that this value points to in memory + /// + /// Sets a watchpoint on the value. + /// + /// @param[in] resolve_location + /// Resolve the location of this value once and watch its address. + /// This value must currently be set to \b true as watching all + /// locations of a variable or a variable path is not yet supported, + /// though we plan to support it in the future. + /// + /// @param[in] read + /// Stop when this value is accessed. + /// + /// @param[in] write + /// Stop when this value is modified + /// + /// @param[out] + /// An error object. Contains the reason if there is some failure. + /// + /// @return + /// An SBWatchpoint object. This object might not be valid upon + /// return due to a value not being contained in memory, too + /// large, or watchpoint resources are not available or all in + /// use. + //------------------------------------------------------------------ + lldb::SBWatchpoint + WatchPointee (bool resolve_location, bool read, bool write, SBError &error); + + //------------------------------------------------------------------ + /// Same as the protected version of GetSP that takes a locker, except that we make the + /// locker locally in the function. Since the Target API mutex is recursive, and the + /// StopLocker is a read lock, you can call this function even if you are already + /// holding the two above-mentioned locks. + /// + /// @return + /// A ValueObjectSP of the best kind (static, dynamic or synthetic) we + /// can cons up, in accordance with the SBValue's settings. + //------------------------------------------------------------------ + lldb::ValueObjectSP + GetSP () const; + +protected: + friend class SBBlock; + friend class SBFrame; + friend class SBTarget; + friend class SBThread; + friend class SBValueList; + + //------------------------------------------------------------------ + /// Get the appropriate ValueObjectSP from this SBValue, consulting the + /// use_dynamic and use_synthetic options passed in to SetSP when the + /// SBValue's contents were set. Since this often requires examining memory, + /// and maybe even running code, it needs to acquire the Target API and Process StopLock. + /// Those are held in an opaque class ValueLocker which is currently local to SBValue.cpp. + /// So you don't have to get these yourself just default construct a ValueLocker, and pass it into this. + /// If we need to make a ValueLocker and use it in some other .cpp file, we'll have to move it to + /// ValueObject.h/cpp or somewhere else convenient. We haven't needed to so far. + /// + /// @param[in] value_locker + /// An object that will hold the Target API, and Process RunLocks, and + /// auto-destroy them when it goes out of scope. Currently this is only useful in + /// SBValue.cpp. + /// + /// @return + /// A ValueObjectSP of the best kind (static, dynamic or synthetic) we + /// can cons up, in accordance with the SBValue's settings. + //------------------------------------------------------------------ + lldb::ValueObjectSP + GetSP (ValueLocker &value_locker) const; + + // these calls do the right thing WRT adjusting their settings according to the target's preferences + void + SetSP (const lldb::ValueObjectSP &sp); + + void + SetSP (const lldb::ValueObjectSP &sp, bool use_synthetic); + + void + SetSP (const lldb::ValueObjectSP &sp, lldb::DynamicValueType use_dynamic); + + void + SetSP (const lldb::ValueObjectSP &sp, lldb::DynamicValueType use_dynamic, bool use_synthetic); + + void + SetSP (const lldb::ValueObjectSP &sp, lldb::DynamicValueType use_dynamic, bool use_synthetic, const char *name); + +private: + typedef std::shared_ptr<ValueImpl> ValueImplSP; + ValueImplSP m_opaque_sp; + + void + SetSP (ValueImplSP impl_sp); +}; + +} // namespace lldb + +#endif // LLDB_SBValue_h_ diff --git a/include/lldb/API/SBValueList.h b/include/lldb/API/SBValueList.h new file mode 100644 index 0000000..b9a6aed --- /dev/null +++ b/include/lldb/API/SBValueList.h @@ -0,0 +1,93 @@ +//===-- SBValueList.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_SBValueList_h_ +#define LLDB_SBValueList_h_ + +#include "lldb/API/SBDefines.h" + +class ValueListImpl; + +namespace lldb { + +class SBValueList +{ +public: + + SBValueList (); + + SBValueList (const lldb::SBValueList &rhs); + + ~SBValueList(); + + bool + IsValid() const; + + void + Clear(); + + void + Append (const lldb::SBValue &val_obj); + + void + Append (const lldb::SBValueList& value_list); + + uint32_t + GetSize() const; + + lldb::SBValue + GetValueAtIndex (uint32_t idx) const; + + lldb::SBValue + FindValueObjectByUID (lldb::user_id_t uid); + + const lldb::SBValueList & + operator = (const lldb::SBValueList &rhs); + +protected: + + // only useful for visualizing the pointer or comparing two SBValueLists + // to see if they are backed by the same underlying Impl. + void * + opaque_ptr (); + +private: + friend class SBFrame; + + SBValueList (const ValueListImpl *lldb_object_ptr); + + void + Append (lldb::ValueObjectSP& val_obj_sp); + + void + CreateIfNeeded (); + + ValueListImpl * + operator -> (); + + ValueListImpl & + operator* (); + + const ValueListImpl * + operator -> () const; + + const ValueListImpl & + operator* () const; + + + ValueListImpl & + ref (); + + std::unique_ptr<ValueListImpl> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBValueList_h_ diff --git a/include/lldb/API/SBWatchpoint.h b/include/lldb/API/SBWatchpoint.h new file mode 100644 index 0000000..9bf51fd1 --- /dev/null +++ b/include/lldb/API/SBWatchpoint.h @@ -0,0 +1,104 @@ +//===-- SBWatchpoint.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_SBWatchpoint_h_ +#define LLDB_SBWatchpoint_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBWatchpoint +{ +public: + + SBWatchpoint (); + + SBWatchpoint (const lldb::SBWatchpoint &rhs); + + SBWatchpoint (const lldb::WatchpointSP &wp_sp); + + ~SBWatchpoint (); + + const lldb::SBWatchpoint & + operator = (const lldb::SBWatchpoint &rhs); + + bool + IsValid() const; + + SBError + GetError(); + + watch_id_t + GetID (); + + /// With -1 representing an invalid hardware index. + int32_t + GetHardwareIndex (); + + lldb::addr_t + GetWatchAddress (); + + size_t + GetWatchSize(); + + void + SetEnabled(bool enabled); + + bool + IsEnabled (); + + uint32_t + GetHitCount (); + + uint32_t + GetIgnoreCount (); + + void + SetIgnoreCount (uint32_t n); + + const char * + GetCondition (); + + void + SetCondition (const char *condition); + + bool + GetDescription (lldb::SBStream &description, DescriptionLevel level); + + void + Clear (); + + lldb::WatchpointSP + GetSP () const; + + void + SetSP (const lldb::WatchpointSP &sp); + + static bool + EventIsWatchpointEvent (const lldb::SBEvent &event); + + static lldb::WatchpointEventType + GetWatchpointEventTypeFromEvent (const lldb::SBEvent& event); + + static lldb::SBWatchpoint + GetWatchpointFromEvent (const lldb::SBEvent& event); + +private: + friend class SBTarget; + friend class SBValue; + + + lldb::WatchpointSP m_opaque_sp; + +}; + +} // namespace lldb + +#endif // LLDB_SBWatchpoint_h_ diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h new file mode 100644 index 0000000..bd11a1c --- /dev/null +++ b/include/lldb/Breakpoint/Breakpoint.h @@ -0,0 +1,630 @@ +//===-- Breakpoint.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_Breakpoint_h_ +#define liblldb_Breakpoint_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointLocationList.h" +#include "lldb/Breakpoint/BreakpointOptions.h" +#include "lldb/Breakpoint/BreakpointLocationCollection.h" +#include "lldb/Breakpoint/Stoppoint.h" +#include "lldb/Core/SearchFilter.h" +#include "lldb/Core/Event.h" +#include "lldb/Core/StringList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Breakpoint Breakpoint.h "lldb/Breakpoint/Breakpoint.h" +/// @brief Class that manages logical breakpoint setting. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// A breakpoint has four main parts, a filter, a resolver, the list of breakpoint +/// locations that have been determined for the filter/resolver pair, and finally +/// a set of options for the breakpoint. +/// +/// \b Filter: +/// This is an object derived from SearchFilter. It manages the search +/// for breakpoint location matches through the symbols in the module list of the target +/// that owns it. It also filters out locations based on whatever logic it wants. +/// +/// \b Resolver: +/// This is an object derived from BreakpointResolver. It provides a +/// callback to the filter that will find breakpoint locations. How it does this is +/// determined by what kind of resolver it is. +/// +/// The Breakpoint class also provides constructors for the common breakpoint cases +/// which make the appropriate filter and resolver for you. +/// +/// \b Location List: +/// This stores the breakpoint locations that have been determined +/// to date. For a given breakpoint, there will be only one location with a given +/// address. Adding a location at an already taken address will just return the location +/// already at that address. Locations can be looked up by ID, or by address. +/// +/// \b Options: +/// This includes: +/// \b Enabled/Disabled +/// \b Ignore Count +/// \b Callback +/// \b Condition +/// Note, these options can be set on the breakpoint, and they can also be set on the +/// individual locations. The options set on the breakpoint take precedence over the +/// options set on the individual location. +/// So for instance disabling the breakpoint will cause NONE of the locations to get hit. +/// But if the breakpoint is enabled, then the location's enabled state will be checked +/// to determine whether to insert that breakpoint location. +/// Similarly, if the breakpoint condition says "stop", we won't check the location's condition. +/// But if the breakpoint condition says "continue", then we will check the location for whether +/// to actually stop or not. +/// One subtle point worth observing here is that you don't actually stop at a Breakpoint, you +/// always stop at one of its locations. So the "should stop" tests are done by the location, +/// not by the breakpoint. +//---------------------------------------------------------------------- +class Breakpoint: + public std::enable_shared_from_this<Breakpoint>, + public Stoppoint +{ +public: + + static const ConstString & + GetEventIdentifier (); + + + //------------------------------------------------------------------ + /// An enum specifying the match style for breakpoint settings. At + /// present only used for function name style breakpoints. + //------------------------------------------------------------------ + typedef enum + { + Exact, + Regexp, + Glob + } MatchType; + + class BreakpointEventData : + public EventData + { + public: + + static const ConstString & + GetFlavorString (); + + virtual const ConstString & + GetFlavor () const; + + BreakpointEventData (lldb::BreakpointEventType sub_type, + const lldb::BreakpointSP &new_breakpoint_sp); + + virtual + ~BreakpointEventData(); + + lldb::BreakpointEventType + GetBreakpointEventType () const; + + lldb::BreakpointSP & + GetBreakpoint (); + + BreakpointLocationCollection & + GetBreakpointLocationCollection() + { + return m_locations; + } + + + virtual void + Dump (Stream *s) const; + + static lldb::BreakpointEventType + GetBreakpointEventTypeFromEvent (const lldb::EventSP &event_sp); + + static lldb::BreakpointSP + GetBreakpointFromEvent (const lldb::EventSP &event_sp); + + static lldb::BreakpointLocationSP + GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t loc_idx); + + static size_t + GetNumBreakpointLocationsFromEvent (const lldb::EventSP &event_sp); + + static const BreakpointEventData * + GetEventDataFromEvent (const Event *event_sp); + + private: + + lldb::BreakpointEventType m_breakpoint_event; + lldb::BreakpointSP m_new_breakpoint_sp; + BreakpointLocationCollection m_locations; + + DISALLOW_COPY_AND_ASSIGN (BreakpointEventData); + }; + + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is not virtual since there should be no reason to subclass + /// breakpoints. The varieties of breakpoints are specified instead by + /// providing different resolvers & filters. + //------------------------------------------------------------------ + ~Breakpoint(); + + //------------------------------------------------------------------ + // Methods + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Tell whether this breakpoint is an "internal" breakpoint. + /// @return + /// Returns \b true if this is an internal breakpoint, \b false otherwise. + //------------------------------------------------------------------ + bool + IsInternal () const; + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void + Dump (Stream *s); + + //------------------------------------------------------------------ + // The next set of methods provide ways to tell the breakpoint to update + // it's location list - usually done when modules appear or disappear. + //------------------------------------------------------------------ + + + //------------------------------------------------------------------ + /// Tell this breakpoint to clear all its breakpoint sites. Done + /// when the process holding the breakpoint sites is destroyed. + //------------------------------------------------------------------ + void + ClearAllBreakpointSites (); + + //------------------------------------------------------------------ + /// Tell this breakpoint to scan it's target's module list and resolve any + /// new locations that match the breakpoint's specifications. + //------------------------------------------------------------------ + void + ResolveBreakpoint (); + + //------------------------------------------------------------------ + /// Tell this breakpoint to scan a given module list and resolve any + /// new locations that match the breakpoint's specifications. + /// + /// @param[in] changed_modules + /// The list of modules to look in for new locations. + //------------------------------------------------------------------ + void + ResolveBreakpointInModules (ModuleList &changed_modules); + + + //------------------------------------------------------------------ + /// Like ResolveBreakpointInModules, but allows for "unload" events, in + /// which case we will remove any locations that are in modules that got + /// unloaded. + /// + /// @param[in] changedModules + /// The list of modules to look in for new locations. + /// @param[in] load_event + /// If \b true then the modules were loaded, if \b false, unloaded. + /// @param[in] delete_locations + /// If \b true then the modules were unloaded delete any locations in the changed modules. + //------------------------------------------------------------------ + void + ModulesChanged (ModuleList &changed_modules, + bool load_event, + bool delete_locations = false); + + + //------------------------------------------------------------------ + /// Tells the breakpoint the old module \a old_module_sp has been + /// replaced by new_module_sp (usually because the underlying file has been + /// rebuilt, and the old version is gone.) + /// + /// @param[in] old_module_sp + /// The old module that is going away. + /// @param[in] new_module_sp + /// The new module that is replacing it. + //------------------------------------------------------------------ + void + ModuleReplaced (lldb::ModuleSP old_module_sp, lldb::ModuleSP new_module_sp); + + //------------------------------------------------------------------ + // The next set of methods provide access to the breakpoint locations + // for this breakpoint. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Add a location to the breakpoint's location list. This is only meant + /// to be called by the breakpoint's resolver. FIXME: how do I ensure that? + /// + /// @param[in] addr + /// The Address specifying the new location. + /// @param[out] new_location + /// Set to \b true if a new location was created, to \b false if there + /// already was a location at this Address. + /// @return + /// Returns a pointer to the new location. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + AddLocation (const Address &addr, + bool *new_location = NULL); + + //------------------------------------------------------------------ + /// Find a breakpoint location by Address. + /// + /// @param[in] addr + /// The Address specifying the location. + /// @return + /// Returns a shared pointer to the location at \a addr. The pointer + /// in the shared pointer will be NULL if there is no location at that address. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + FindLocationByAddress (const Address &addr); + + //------------------------------------------------------------------ + /// Find a breakpoint location ID by Address. + /// + /// @param[in] addr + /// The Address specifying the location. + /// @return + /// Returns the UID of the location at \a addr, or \b LLDB_INVALID_ID if + /// there is no breakpoint location at that address. + //------------------------------------------------------------------ + lldb::break_id_t + FindLocationIDByAddress (const Address &addr); + + //------------------------------------------------------------------ + /// Find a breakpoint location for a given breakpoint location ID. + /// + /// @param[in] bp_loc_id + /// The ID specifying the location. + /// @return + /// Returns a shared pointer to the location with ID \a bp_loc_id. The pointer + /// in the shared pointer will be NULL if there is no location with that ID. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + FindLocationByID (lldb::break_id_t bp_loc_id); + + //------------------------------------------------------------------ + /// Get breakpoint locations by index. + /// + /// @param[in] index + /// The location index. + /// + /// @return + /// Returns a shared pointer to the location with index \a + /// index. The shared pointer might contain NULL if \a index is + /// greater than then number of actual locations. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + GetLocationAtIndex (size_t index); + + //------------------------------------------------------------------ + // The next section deals with various breakpoint options. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false disable it. + //------------------------------------------------------------------ + void + SetEnabled (bool enable); + + //------------------------------------------------------------------ + /// Check the Enable/Disable state. + /// @return + /// \b true if the breakpoint is enabled, \b false if disabled. + //------------------------------------------------------------------ + bool + IsEnabled (); + + //------------------------------------------------------------------ + /// Set the breakpoint to ignore the next \a count breakpoint hits. + /// @param[in] count + /// The number of breakpoint hits to ignore. + //------------------------------------------------------------------ + void + SetIgnoreCount (uint32_t count); + + //------------------------------------------------------------------ + /// Return the current ignore count/ + /// @return + /// The number of breakpoint hits to be ignored. + //------------------------------------------------------------------ + uint32_t + GetIgnoreCount () const; + + //------------------------------------------------------------------ + /// Return the current hit count for all locations. + /// @return + /// The current hit count for all locations. + //------------------------------------------------------------------ + uint32_t + GetHitCount () const; + + + //------------------------------------------------------------------ + /// If \a one_shot is \b true, breakpoint will be deleted on first hit. + //------------------------------------------------------------------ + void + SetOneShot (bool one_shot); + + //------------------------------------------------------------------ + /// Check the OneShot state. + /// @return + /// \b true if the breakpoint is one shot, \b false otherwise. + //------------------------------------------------------------------ + bool + IsOneShot () const; + + //------------------------------------------------------------------ + /// Set the valid thread to be checked when the breakpoint is hit. + /// @param[in] thread_id + /// If this thread hits the breakpoint, we stop, otherwise not. + //------------------------------------------------------------------ + void + SetThreadID (lldb::tid_t thread_id); + + //------------------------------------------------------------------ + /// Return the current stop thread value. + /// @return + /// The thread id for which the breakpoint hit will stop, LLDB_INVALID_THREAD_ID for all threads. + //------------------------------------------------------------------ + lldb::tid_t + GetThreadID () const; + + void + SetThreadIndex (uint32_t index); + + uint32_t + GetThreadIndex() const; + + void + SetThreadName (const char *thread_name); + + const char * + GetThreadName () const; + + void + SetQueueName (const char *queue_name); + + const char * + GetQueueName () const; + + //------------------------------------------------------------------ + /// Set the callback action invoked when the breakpoint is hit. + /// + /// @param[in] callback + /// The method that will get called when the breakpoint is hit. + /// @param[in] baton + /// A void * pointer that will get passed back to the callback function. + /// @param[in] is_synchronous + /// If \b true the callback will be run on the private event thread + /// before the stop event gets reported. If false, the callback will get + /// handled on the public event thead after the stop has been posted. + /// + /// @return + /// \b true if the process should stop when you hit the breakpoint. + /// \b false if it should continue. + //------------------------------------------------------------------ + void + SetCallback (BreakpointHitCallback callback, + void *baton, + bool is_synchronous = false); + + void + SetCallback (BreakpointHitCallback callback, + const lldb::BatonSP &callback_baton_sp, + bool is_synchronous = false); + + void + ClearCallback (); + + //------------------------------------------------------------------ + /// Set the breakpoint's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the breakpoint is hit. + /// Pass in NULL to clear the condition. + //------------------------------------------------------------------ + void SetCondition (const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or NULL if no + // condition has been set. + //------------------------------------------------------------------ + const char *GetConditionText () const; + + //------------------------------------------------------------------ + // The next section are various utility functions. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Return the number of breakpoint locations that have resolved to + /// actual breakpoint sites. + /// + /// @return + /// The number locations resolved breakpoint sites. + //------------------------------------------------------------------ + size_t + GetNumResolvedLocations() const; + + //------------------------------------------------------------------ + /// Return the number of breakpoint locations. + /// + /// @return + /// The number breakpoint locations. + //------------------------------------------------------------------ + size_t + GetNumLocations() const; + + //------------------------------------------------------------------ + /// Put a description of this breakpoint into the stream \a s. + /// + /// @param[in] s + /// Stream into which to dump the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void + GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations = false); + + //------------------------------------------------------------------ + /// Set the "kind" description for a breakpoint. If the breakpoint is hit + /// the stop info will show this "kind" description instead of the breakpoint + /// number. Mostly useful for internal breakpoints, where the breakpoint number + /// doesn't have meaning to the user. + /// + /// @param[in] kind + /// New "kind" description. + //------------------------------------------------------------------ + void + SetBreakpointKind (const char *kind) + { + m_kind_description.assign (kind); + } + + //------------------------------------------------------------------ + /// Return the "kind" description for a breakpoint. + /// + /// @return + /// The breakpoint kind, or NULL if none is set. + //------------------------------------------------------------------ + const char *GetBreakpointKind () const + { + return m_kind_description.c_str(); + } + + //------------------------------------------------------------------ + /// Accessor for the breakpoint Target. + /// @return + /// This breakpoint's Target. + //------------------------------------------------------------------ + Target & + GetTarget (); + + const Target & + GetTarget () const; + + void + GetResolverDescription (Stream *s); + + //------------------------------------------------------------------ + /// Find breakpoint locations which match the (filename, line_number) description. + /// The breakpoint location collection is to be filled with the matching locations. + /// It should be initialized with 0 size by the API client. + /// + /// @return + /// True if there is a match + /// + /// The locations which match the filename and line_number in loc_coll. If its + /// size is 0 and true is returned, it means the breakpoint fully matches the + /// description. + //------------------------------------------------------------------ + bool GetMatchingFileLine(const ConstString &filename, uint32_t line_number, + BreakpointLocationCollection &loc_coll); + + void + GetFilterDescription (Stream *s); + + //------------------------------------------------------------------ + /// Returns the BreakpointOptions structure set at the breakpoint level. + /// + /// Meant to be used by the BreakpointLocation class. + /// + /// @return + /// A pointer to this breakpoint's BreakpointOptions. + //------------------------------------------------------------------ + BreakpointOptions * + GetOptions (); + + + //------------------------------------------------------------------ + /// Invoke the callback action when the breakpoint is hit. + /// + /// Meant to be used by the BreakpointLocation class. + /// + /// @param[in] context + /// Described the breakpoint event. + /// + /// @param[in] bp_loc_id + /// Which breakpoint location hit this breakpoint. + /// + /// @return + /// \b true if the target should stop at this breakpoint and \b false not. + //------------------------------------------------------------------ + bool + InvokeCallback (StoppointCallbackContext *context, + lldb::break_id_t bp_loc_id); + +protected: + friend class Target; + //------------------------------------------------------------------ + // Protected Methods + //------------------------------------------------------------------ + + + //------------------------------------------------------------------ + /// Constructors and Destructors + /// Only the Target can make a breakpoint, and it owns the breakpoint lifespans. + /// The constructor takes a filter and a resolver. Up in Target there are convenience + /// variants that make breakpoints for some common cases. + //------------------------------------------------------------------ + // This is the generic constructor + Breakpoint(Target &target, lldb::SearchFilterSP &filter_sp, lldb::BreakpointResolverSP &resolver_sp); + + friend class BreakpointLocation; // To call the following two when determining whether to stop. + + void + DecrementIgnoreCount(); + + // BreakpointLocation::IgnoreCountShouldStop & Breakpoint::IgnoreCountShouldStop can only be called once per stop, + // and BreakpointLocation::IgnoreCountShouldStop should be tested first, and if it returns false we should + // continue, otherwise we should test Breakpoint::IgnoreCountShouldStop. + + bool + IgnoreCountShouldStop (); + +private: + //------------------------------------------------------------------ + // For Breakpoint only + //------------------------------------------------------------------ + bool m_being_created; + Target &m_target; // The target that holds this breakpoint. + lldb::SearchFilterSP m_filter_sp; // The filter that constrains the breakpoint's domain. + lldb::BreakpointResolverSP m_resolver_sp; // The resolver that defines this breakpoint. + BreakpointOptions m_options; // Settable breakpoint options + BreakpointLocationList m_locations; // The list of locations currently found for this breakpoint. + std::string m_kind_description; + + void + SendBreakpointChangedEvent (lldb::BreakpointEventType eventKind); + + void + SendBreakpointChangedEvent (BreakpointEventData *data); + + DISALLOW_COPY_AND_ASSIGN(Breakpoint); +}; + +} // namespace lldb_private + +#endif // liblldb_Breakpoint_h_ diff --git a/include/lldb/Breakpoint/BreakpointID.h b/include/lldb/Breakpoint/BreakpointID.h new file mode 100644 index 0000000..9e35210 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointID.h @@ -0,0 +1,117 @@ +//===-- BreakpointID.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_BreakpointID_h_ +#define liblldb_BreakpointID_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// class BreakpointID +//---------------------------------------------------------------------- + +class BreakpointID +{ +public: + + BreakpointID (lldb::break_id_t bp_id = LLDB_INVALID_BREAK_ID, + lldb::break_id_t loc_id = LLDB_INVALID_BREAK_ID); + + virtual + ~BreakpointID (); + + lldb::break_id_t + GetBreakpointID () + { + return m_break_id; + } + + lldb::break_id_t + GetLocationID () + { + return m_location_id; + } + + void + SetID (lldb::break_id_t bp_id, lldb::break_id_t loc_id) + { + m_break_id = bp_id; + m_location_id = loc_id; + } + + void + SetBreakpointID (lldb::break_id_t bp_id) + { + m_break_id = bp_id; + } + + void + SetBreakpointLocationID (lldb::break_id_t loc_id) + { + m_location_id = loc_id; + } + + void + GetDescription (Stream *s, lldb::DescriptionLevel level); + + static bool + IsRangeIdentifier (const char *str); + + static bool + IsValidIDExpression (const char *str); + + static const char *g_range_specifiers[]; + + //------------------------------------------------------------------ + /// Takes an input string containing the description of a breakpoint or breakpoint and location + /// and returns the breakpoint ID and the breakpoint location id. + /// + /// @param[in] input + /// A string containing JUST the breakpoint description. + /// @param[out] break_id + /// This is the break id. + /// @param[out] break_loc_id + /// This is breakpoint location id, or LLDB_INVALID_BREAK_ID is no location was specified. + /// @return + /// \b true if the call was able to extract a breakpoint location from the string. \b false otherwise. + //------------------------------------------------------------------ + static bool + ParseCanonicalReference (const char *input, lldb::break_id_t *break_id, lldb::break_id_t *break_loc_id); + + + //------------------------------------------------------------------ + /// Takes a breakpoint ID and the breakpoint location id and returns + /// a string containing the canonical description for the breakpoint + /// or breakpoint location. + /// + /// @param[out] break_id + /// This is the break id. + /// + /// @param[out] break_loc_id + /// This is breakpoint location id, or LLDB_INVALID_BREAK_ID is no + /// location is to be specified. + //------------------------------------------------------------------ + static void + GetCanonicalReference (Stream *s, lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + +protected: + lldb::break_id_t m_break_id; + lldb::break_id_t m_location_id; +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointID_h_ diff --git a/include/lldb/Breakpoint/BreakpointIDList.h b/include/lldb/Breakpoint/BreakpointIDList.h new file mode 100644 index 0000000..c9fcef0 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointIDList.h @@ -0,0 +1,82 @@ +//===-- BreakpointIDList.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_BreakpointIDList_h_ +#define liblldb_BreakpointIDList_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" +#include "lldb/Breakpoint/BreakpointID.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// class BreakpointIDList +//---------------------------------------------------------------------- + + +class BreakpointIDList +{ +public: + typedef std::vector<BreakpointID> BreakpointIDArray; + + BreakpointIDList (); + + virtual + ~BreakpointIDList (); + + size_t + GetSize(); + + BreakpointID & + GetBreakpointIDAtIndex (size_t index); + + bool + RemoveBreakpointIDAtIndex (size_t index); + + void + Clear(); + + bool + AddBreakpointID (BreakpointID bp_id); + + bool + AddBreakpointID (const char *bp_id); + + bool + FindBreakpointID (BreakpointID &bp_id, size_t *position); + + bool + FindBreakpointID (const char *bp_id, size_t *position); + + void + InsertStringArray (const char **string_array, size_t array_size, CommandReturnObject &result); + + static bool + StringContainsIDRangeExpression (const char *in_string, size_t *range_start_len, size_t *range_end_pos); + + static void + FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, Args &new_args); + +private: + BreakpointIDArray m_breakpoint_ids; + BreakpointID m_invalid_id; + + DISALLOW_COPY_AND_ASSIGN(BreakpointIDList); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointIDList_h_ diff --git a/include/lldb/Breakpoint/BreakpointList.h b/include/lldb/Breakpoint/BreakpointList.h new file mode 100644 index 0000000..97eb2b4 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointList.h @@ -0,0 +1,193 @@ +//===-- BreakpointList.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_BreakpointList_h_ +#define liblldb_BreakpointList_h_ + +// C Includes +// C++ Includes +#include <list> +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/Breakpoint.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointList BreakpointList.h "lldb/Breakpoint/BreakpointList.h" +/// @brief This class manages a list of breakpoints. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// Allows adding and removing breakpoints and find by ID and index. +//---------------------------------------------------------------------- + +class BreakpointList +{ +public: + BreakpointList (bool is_internal); + + ~BreakpointList(); + + //------------------------------------------------------------------ + /// Add the breakpoint \a bp_sp to the list. + /// + /// @param[in] bp_sp + /// Shared pointer to the breakpoint that will get added to the list. + /// + /// @result + /// Returns breakpoint id. + //------------------------------------------------------------------ + lldb::break_id_t + Add (lldb::BreakpointSP& bp_sp, bool notify); + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with id \a breakID. + /// + /// @param[in] breakID + /// The breakpoint ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointSP + FindBreakpointByID (lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with id \a breakID. Const version. + /// + /// @param[in] breakID + /// The breakpoint ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointSP + FindBreakpointByID (lldb::break_id_t breakID) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with index \a i. + /// + /// @param[in] i + /// The breakpoint index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointSP + GetBreakpointAtIndex (size_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint with index \a i, const version + /// + /// @param[in] i + /// The breakpoint index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointSP + GetBreakpointAtIndex (size_t i) const; + + //------------------------------------------------------------------ + /// Returns the number of elements in this breakpoint list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t + GetSize() const + { + Mutex::Locker locker(m_mutex); + return m_breakpoints.size(); + } + + //------------------------------------------------------------------ + /// Removes the breakpoint given by \b breakID from this list. + /// + /// @param[in] breakID + /// The breakpoint index to remove. + /// + /// @result + /// \b true if the breakpoint \a breakID was in the list. + //------------------------------------------------------------------ + bool + Remove (lldb::break_id_t breakID, bool notify); + + void + SetEnabledAll (bool enabled); + + //------------------------------------------------------------------ + /// Removes all the breakpoints from this list. + //------------------------------------------------------------------ + void + RemoveAll (bool notify); + + //------------------------------------------------------------------ + /// Tell all the breakpoints to update themselves due to a change in the + /// modules in \a module_list. \a added says whether the module was loaded + /// or unloaded. + /// + /// @param[in] module_list + /// The module list that has changed. + /// + /// @param[in] added + /// \b true if the modules are loaded, \b false if unloaded. + //------------------------------------------------------------------ + void + UpdateBreakpoints (ModuleList &module_list, bool added); + + void + UpdateBreakpointsWhenModuleIsReplaced (lldb::ModuleSP old_module_sp, lldb::ModuleSP new_module_sp); + + void + ClearAllBreakpointSites (); + + //------------------------------------------------------------------ + /// Sets the passed in Locker to hold the Breakpoint List mutex. + /// + /// @param[in] locker + /// The locker object that is set. + //------------------------------------------------------------------ + void + GetListMutex (lldb_private::Mutex::Locker &locker); + +protected: + typedef std::list<lldb::BreakpointSP> bp_collection; + + bp_collection::iterator + GetBreakpointIDIterator(lldb::break_id_t breakID); + + bp_collection::const_iterator + GetBreakpointIDConstIterator(lldb::break_id_t breakID) const; + + mutable Mutex m_mutex; + bp_collection m_breakpoints; // The breakpoint list, currently a list. + lldb::break_id_t m_next_break_id; + bool m_is_internal; + +private: + DISALLOW_COPY_AND_ASSIGN (BreakpointList); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointList_h_ diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h new file mode 100644 index 0000000..9ab0a79 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointLocation.h @@ -0,0 +1,401 @@ +//===-- BreakpointLocation.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_BreakpointLocation_h_ +#define liblldb_BreakpointLocation_h_ + +// C Includes + +// C++ Includes +#include <list> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Breakpoint/StoppointLocation.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/StringList.h" +#include "lldb/Core/UserID.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/Process.h" +#include "lldb/Expression/ClangUserExpression.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointLocation BreakpointLocation.h "lldb/Breakpoint/BreakpointLocation.h" +/// @brief Class that manages one unique (by address) instance of a logical breakpoint. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// A breakpoint location is defined by the breakpoint that produces it, +/// and the address that resulted in this particular instantiation. +/// Each breakpoint location also may have a breakpoint site if its +/// address has been loaded into the program. +/// Finally it has a settable options object. +/// +/// FIXME: Should we also store some fingerprint for the location, so +/// we can map one location to the "equivalent location" on rerun? This +/// would be useful if you've set options on the locations. +//---------------------------------------------------------------------- + +class BreakpointLocation : + public std::enable_shared_from_this<BreakpointLocation>, + public StoppointLocation +{ +public: + + ~BreakpointLocation (); + + //------------------------------------------------------------------ + /// Gets the load address for this breakpoint location + /// @return + /// Returns breakpoint location load address, \b + /// LLDB_INVALID_ADDRESS if not yet set. + //------------------------------------------------------------------ + lldb::addr_t + GetLoadAddress () const; + + //------------------------------------------------------------------ + /// Gets the Address for this breakpoint location + /// @return + /// Returns breakpoint location Address. + //------------------------------------------------------------------ + Address & + GetAddress (); + //------------------------------------------------------------------ + /// Gets the Breakpoint that created this breakpoint location + /// @return + /// Returns the owning breakpoint. + //------------------------------------------------------------------ + Breakpoint & + GetBreakpoint (); + + //------------------------------------------------------------------ + /// Determines whether we should stop due to a hit at this + /// breakpoint location. + /// + /// Side Effects: This may evaluate the breakpoint condition, and + /// run the callback. So this command may do a considerable amount + /// of work. + /// + /// @return + /// \b true if this breakpoint location thinks we should stop, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + ShouldStop (StoppointCallbackContext *context); + + //------------------------------------------------------------------ + // The next section deals with various breakpoint options. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false + /// disable it. + //------------------------------------------------------------------ + void + SetEnabled(bool enabled); + + //------------------------------------------------------------------ + /// Check the Enable/Disable state. + /// + /// @return + /// \b true if the breakpoint is enabled, \b false if disabled. + //------------------------------------------------------------------ + bool + IsEnabled () const; + + //------------------------------------------------------------------ + /// Return the current Ignore Count. + /// + /// @return + /// The number of breakpoint hits to be ignored. + //------------------------------------------------------------------ + uint32_t + GetIgnoreCount (); + + //------------------------------------------------------------------ + /// Set the breakpoint to ignore the next \a count breakpoint hits. + /// + /// @param[in] count + /// The number of breakpoint hits to ignore. + //------------------------------------------------------------------ + void + SetIgnoreCount (uint32_t n); + + //------------------------------------------------------------------ + /// Set the callback action invoked when the breakpoint is hit. + /// + /// The callback will return a bool indicating whether the target + /// should stop at this breakpoint or not. + /// + /// @param[in] callback + /// The method that will get called when the breakpoint is hit. + /// + /// @param[in] callback_baton_sp + /// A shared pointer to a Baton that provides the void * needed + /// for the callback. + /// + /// @see lldb_private::Baton + //------------------------------------------------------------------ + void + SetCallback (BreakpointHitCallback callback, + const lldb::BatonSP &callback_baton_sp, + bool is_synchronous); + + void + SetCallback (BreakpointHitCallback callback, + void *baton, + bool is_synchronous); + + void + ClearCallback (); + + //------------------------------------------------------------------ + /// Set the breakpoint location's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the breakpoint is hit. + //------------------------------------------------------------------ + void + SetCondition (const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or NULL if no + // condition has been set. + //------------------------------------------------------------------ + const char * + GetConditionText (size_t *hash = NULL) const; + + bool + ConditionSaysStop (ExecutionContext &exe_ctx, Error &error); + + + //------------------------------------------------------------------ + /// Set the valid thread to be checked when the breakpoint is hit. + /// + /// @param[in] thread_id + /// If this thread hits the breakpoint, we stop, otherwise not. + //------------------------------------------------------------------ + void + SetThreadID (lldb::tid_t thread_id); + + lldb::tid_t + GetThreadID (); + + void + SetThreadIndex (uint32_t index); + + uint32_t + GetThreadIndex() const; + + void + SetThreadName (const char *thread_name); + + const char * + GetThreadName () const; + + void + SetQueueName (const char *queue_name); + + const char * + GetQueueName () const; + + //------------------------------------------------------------------ + // The next section deals with this location's breakpoint sites. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Try to resolve the breakpoint site for this location. + /// + /// @return + /// \b true if we were successful at setting a breakpoint site, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + ResolveBreakpointSite (); + + //------------------------------------------------------------------ + /// Clear this breakpoint location's breakpoint site - for instance + /// when disabling the breakpoint. + /// + /// @return + /// \b true if there was a breakpoint site to be cleared, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + ClearBreakpointSite (); + + //------------------------------------------------------------------ + /// Return whether this breakpoint location has a breakpoint site. + /// @return + /// \b true if there was a breakpoint site for this breakpoint + /// location, \b false otherwise. + //------------------------------------------------------------------ + bool + IsResolved () const; + + lldb::BreakpointSiteSP + GetBreakpointSite() const; + + //------------------------------------------------------------------ + // The next section are generic report functions. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Print a description of this breakpoint location to the stream + /// \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void + GetDescription (Stream *s, lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + //------------------------------------------------------------------ + /// Use this to set location specific breakpoint options. + /// + /// It will create a copy of the containing breakpoint's options if + /// that hasn't been done already + /// + /// @return + /// A pointer to the breakpoint options. + //------------------------------------------------------------------ + BreakpointOptions * + GetLocationOptions (); + + //------------------------------------------------------------------ + /// Use this to access breakpoint options from this breakpoint location. + /// This will point to the owning breakpoint's options unless options have + /// been set specifically on this location. + /// + /// @return + /// A pointer to the containing breakpoint's options if this + /// location doesn't have its own copy. + //------------------------------------------------------------------ + const BreakpointOptions * + GetOptionsNoCreate () const; + + bool + ValidForThisThread (Thread *thread); + + + //------------------------------------------------------------------ + /// Invoke the callback action when the breakpoint is hit. + /// + /// Meant to be used by the BreakpointLocation class. + /// + /// @param[in] context + /// Described the breakpoint event. + /// + /// @param[in] bp_loc_id + /// Which breakpoint location hit this breakpoint. + /// + /// @return + /// \b true if the target should stop at this breakpoint and \b + /// false not. + //------------------------------------------------------------------ + bool + InvokeCallback (StoppointCallbackContext *context); + +protected: + friend class BreakpointLocationList; + friend class CommandObjectBreakpointCommandAdd; + friend class Process; + + //------------------------------------------------------------------ + /// Set the breakpoint site for this location to \a bp_site_sp. + /// + /// @param[in] bp_site_sp + /// The breakpoint site we are setting for this location. + /// + /// @return + /// \b true if we were successful at setting the breakpoint site, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + SetBreakpointSite (lldb::BreakpointSiteSP& bp_site_sp); + + void + DecrementIgnoreCount(); + + bool + IgnoreCountShouldStop(); + +private: + + //------------------------------------------------------------------ + // Constructors and Destructors + // + // Only the Breakpoint can make breakpoint locations, and it owns + // them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Constructor. + /// + /// @param[in] owner + /// A back pointer to the breakpoint that owns this location. + /// + /// @param[in] addr + /// The Address defining this location. + /// + /// @param[in] tid + /// The thread for which this breakpoint location is valid, or + /// LLDB_INVALID_THREAD_ID if it is valid for all threads. + /// + /// @param[in] hardware + /// \b true if a hardware breakpoint is requested. + //------------------------------------------------------------------ + + BreakpointLocation (lldb::break_id_t bid, + Breakpoint &owner, + const Address &addr, + lldb::tid_t tid = LLDB_INVALID_THREAD_ID, + bool hardware = false); + + //------------------------------------------------------------------ + // Data members: + //------------------------------------------------------------------ + bool m_being_created; + Address m_address; ///< The address defining this location. + Breakpoint &m_owner; ///< The breakpoint that produced this object. + std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options. + lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.) + ClangUserExpression::ClangUserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition. + Mutex m_condition_mutex; ///< Guards parsing and evaluation of the condition, which could be evaluated by multiple processes. + size_t m_condition_hash; ///< For testing whether the condition source code changed. + + void + SendBreakpointLocationChangedEvent (lldb::BreakpointEventType eventKind); + + DISALLOW_COPY_AND_ASSIGN (BreakpointLocation); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointLocation_h_ diff --git a/include/lldb/Breakpoint/BreakpointLocationCollection.h b/include/lldb/Breakpoint/BreakpointLocationCollection.h new file mode 100644 index 0000000..7f6a659 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointLocationCollection.h @@ -0,0 +1,209 @@ +//===-- BreakpointLocationCollection.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_BreakpointLocationCollection_h_ +#define liblldb_BreakpointLocationCollection_h_ + +// C Includes +// C++ Includes +#include <vector> +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class BreakpointLocationCollection +{ +public: + BreakpointLocationCollection(); + + ~BreakpointLocationCollection(); + + //------------------------------------------------------------------ + /// Add the breakpoint \a bp_loc_sp to the list. + /// + /// @param[in] bp_sp + /// Shared pointer to the breakpoint location that will get added + /// to the list. + /// + /// @result + /// Returns breakpoint location id. + //------------------------------------------------------------------ + void + Add (const lldb::BreakpointLocationSP& bp_loc_sp); + + //------------------------------------------------------------------ + /// Removes the breakpoint location given by \b breakID from this + /// list. + /// + /// @param[in] break_id + /// The breakpoint index to remove. + /// + /// @param[in] break_loc_id + /// The breakpoint location index in break_id to remove. + /// + /// @result + /// \b true if the breakpoint was in the list. + //------------------------------------------------------------------ + bool + Remove (lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with id \a + /// breakID. + /// + /// @param[in] break_id + /// The breakpoint ID to seek for. + /// + /// @param[in] break_loc_id + /// The breakpoint location ID in \a break_id to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with id \a + /// breakID, const version. + /// + /// @param[in] breakID + /// The breakpoint location ID to seek for. + /// + /// @param[in] break_loc_id + /// The breakpoint location ID in \a break_id to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP + FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with index + /// \a i. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + GetByIndex (size_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with index + /// \a i, const version. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP + GetByIndex (size_t i) const; + + //------------------------------------------------------------------ + /// Returns the number of elements in this breakpoint location list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t + GetSize() const { return m_break_loc_collection.size(); } + + //------------------------------------------------------------------ + /// Enquires of all the breakpoint locations in this list whether + /// we should stop at a hit at \a breakID. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] breakID + /// This break ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool + ShouldStop (StoppointCallbackContext *context); + + //------------------------------------------------------------------ + /// Print a description of the breakpoint locations in this list + /// to the stream \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void GetDescription (Stream *s, lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Check whether this collection of breakpoint locations have any + /// thread specifiers, and if yes, is \a thread_id contained in any + /// of these specifiers. + /// + /// @param[in] thread + /// The thread against which to test. + /// + /// return + /// \b true if the collection contains at least one location that + /// would be valid for this thread, false otherwise. + //------------------------------------------------------------------ + bool ValidForThisThread (Thread *thread); + + //------------------------------------------------------------------ + /// Tell whether ALL the breakpoints in the location collection are internal. + /// + /// @result + /// \b true if all breakpoint locations are owned by internal breakpoints, + /// \b false otherwise. + //------------------------------------------------------------------ + bool IsInternal() const; + + +protected: + //------------------------------------------------------------------ + // Classes that inherit from BreakpointLocationCollection can see + // and modify these + //------------------------------------------------------------------ + +private: + //------------------------------------------------------------------ + // For BreakpointLocationCollection only + //------------------------------------------------------------------ + + typedef std::vector<lldb::BreakpointLocationSP> collection; + + collection::iterator + GetIDPairIterator(lldb::break_id_t break_id, lldb::break_id_t break_loc_id); + + collection::const_iterator + GetIDPairConstIterator(lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const; + + collection m_break_loc_collection; + +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointLocationCollection_h_ diff --git a/include/lldb/Breakpoint/BreakpointLocationList.h b/include/lldb/Breakpoint/BreakpointLocationList.h new file mode 100644 index 0000000..1cba23d --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointLocationList.h @@ -0,0 +1,269 @@ +//===-- BreakpointLocationList.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_BreakpointLocationList_h_ +#define liblldb_BreakpointLocationList_h_ + +// C Includes +// C++ Includes +#include <vector> +#include <map> +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointLocationList BreakpointLocationList.h "lldb/Breakpoint/BreakpointLocationList.h" +/// @brief This class is used by Breakpoint to manage a list of breakpoint locations, +// each breakpoint location in the list +/// has a unique ID, and is unique by Address as well. +//---------------------------------------------------------------------- + +class BreakpointLocationList +{ +// Only Breakpoints can make the location list, or add elements to it. +// This is not just some random collection of locations. Rather, the act of adding the location +// to this list sets its ID, and implicitly all the locations have the same breakpoint ID as +// well. If you need a generic container for breakpoint locations, use BreakpointLocationCollection. +friend class Breakpoint; + +public: + virtual + ~BreakpointLocationList(); + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location at address + /// \a addr - const version. + /// + /// @param[in] addr + /// The address to look for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP + FindByAddress (const Address &addr) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with id + /// \a breakID, const version. + /// + /// @param[in] breakID + /// The breakpoint location ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + FindByID (lldb::break_id_t breakID) const; + + //------------------------------------------------------------------ + /// Returns the breakpoint location id to the breakpoint location + /// at address \a addr. + /// + /// @param[in] addr + /// The address to match. + /// + /// @result + /// The ID of the breakpoint location, or LLDB_INVALID_BREAK_ID. + //------------------------------------------------------------------ + lldb::break_id_t + FindIDByAddress (const Address &addr); + + //------------------------------------------------------------------ + /// Returns a breakpoint location list of the breakpoint locations + /// in the module \a module. This list is allocated, and owned by + /// the caller. + /// + /// @param[in] module + /// The module to seek in. + /// + /// @param[in] + /// A breakpoint collection that gets any breakpoint locations + /// that match \a module appended to. + /// + /// @result + /// The number of matches + //------------------------------------------------------------------ + size_t + FindInModule (Module *module, + BreakpointLocationCollection& bp_loc_list); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with + /// index \a i. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + GetByIndex (size_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint location with index + /// \a i, const version. + /// + /// @param[in] i + /// The breakpoint location index to seek for. + /// + /// @result + /// A shared pointer to the breakpoint. May contain a NULL + /// pointer if the breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointLocationSP + GetByIndex (size_t i) const; + + //------------------------------------------------------------------ + /// Removes all the locations in this list from their breakpoint site + /// owners list. + //------------------------------------------------------------------ + void + ClearAllBreakpointSites (); + + //------------------------------------------------------------------ + /// Tells all the breakopint locations in this list to attempt to + /// resolve any possible breakpoint sites. + //------------------------------------------------------------------ + void + ResolveAllBreakpointSites (); + + //------------------------------------------------------------------ + /// Returns the number of breakpoint locations in this list with + /// resolved breakpoints. + /// + /// @result + /// Number of qualifying breakpoint locations. + //------------------------------------------------------------------ + size_t + GetNumResolvedLocations() const; + + //------------------------------------------------------------------ + /// Returns the number hit count of all locations in this list. + /// + /// @result + /// Hit count of all locations in this list. + //------------------------------------------------------------------ + uint32_t + GetHitCount () const; + + //------------------------------------------------------------------ + /// Enquires of the breakpoint location in this list with ID \a + /// breakID whether we should stop. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] breakID + /// This break ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool + ShouldStop (StoppointCallbackContext *context, + lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns the number of elements in this breakpoint location list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t + GetSize() const + { + return m_locations.size(); + } + + //------------------------------------------------------------------ + /// Print a description of the breakpoint locations in this list to + /// the stream \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void + GetDescription (Stream *s, + lldb::DescriptionLevel level); + +protected: + + //------------------------------------------------------------------ + /// This is the standard constructor. + /// + /// It creates an empty breakpoint location list. It is protected + /// here because only Breakpoints are allowed to create the + /// breakpoint location list. + //------------------------------------------------------------------ + BreakpointLocationList(Breakpoint &owner); + + //------------------------------------------------------------------ + /// Add the breakpoint \a bp_loc_sp to the list. + /// + /// @param[in] bp_sp + /// Shared pointer to the breakpoint location that will get + /// added to the list. + /// + /// @result + /// Returns breakpoint location id. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + Create (const Address &addr); + + void + StartRecordingNewLocations(BreakpointLocationCollection &new_locations); + + void + StopRecordingNewLocations(); + + lldb::BreakpointLocationSP + AddLocation (const Address &addr, + bool *new_location = NULL); + + bool + RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp); + + typedef std::vector<lldb::BreakpointLocationSP> collection; + typedef std::map<lldb_private::Address, + lldb::BreakpointLocationSP, + Address::ModulePointerAndOffsetLessThanFunctionObject> addr_map; + + Breakpoint &m_owner; + collection m_locations; + addr_map m_address_to_location; + mutable Mutex m_mutex; + lldb::break_id_t m_next_id; + BreakpointLocationCollection *m_new_location_recorder; +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointLocationList_h_ diff --git a/include/lldb/Breakpoint/BreakpointOptions.h b/include/lldb/Breakpoint/BreakpointOptions.h new file mode 100644 index 0000000..728f593 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointOptions.h @@ -0,0 +1,358 @@ +//===-- BreakpointOptions.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_BreakpointOptions_h_ +#define liblldb_BreakpointOptions_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Baton.h" +#include "lldb/Core/StringList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointOptions BreakpointOptions.h "lldb/Breakpoint/BreakpointOptions.h" +/// @brief Class that manages the options on a breakpoint or breakpoint location. +//---------------------------------------------------------------------- + +class BreakpointOptions +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Default constructor. The breakpoint is enabled, and has no condition, + /// callback, ignore count, etc... + //------------------------------------------------------------------ + BreakpointOptions(); + BreakpointOptions(const BreakpointOptions& rhs); + + static BreakpointOptions * + CopyOptionsNoCallback (BreakpointOptions &rhs); + //------------------------------------------------------------------ + /// This constructor allows you to specify all the breakpoint options. + /// + /// @param[in] condition + /// The expression which if it evaluates to \b true if we are to stop + /// + /// @param[in] callback + /// This is the plugin for some code that gets run, returns \b true if we are to stop. + /// + /// @param[in] baton + /// Client data that will get passed to the callback. + /// + /// @param[in] enabled + /// Is this breakpoint enabled. + /// + /// @param[in] ignore + /// How many breakpoint hits we should ignore before stopping. + /// + /// @param[in] thread_id + /// Only stop if \a thread_id hits the breakpoint. + //------------------------------------------------------------------ + BreakpointOptions(void *condition, + BreakpointHitCallback callback, + void *baton, + bool enabled = true, + int32_t ignore = 0, + lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID, + bool one_shot = false); + + virtual ~BreakpointOptions(); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const BreakpointOptions& + operator=(const BreakpointOptions& rhs); + + //------------------------------------------------------------------ + // Callbacks + // + // Breakpoint callbacks come in two forms, synchronous and asynchronous. Synchronous callbacks will get + // run before any of the thread plans are consulted, and if they return false the target will continue + // "under the radar" of the thread plans. There are a couple of restrictions to synchronous callbacks: + // 1) They should NOT resume the target themselves. Just return false if you want the target to restart. + // 2) Breakpoints with synchronous callbacks can't have conditions (or rather, they can have them, but they + // won't do anything. Ditto with ignore counts, etc... You are supposed to control that all through the + // callback. + // Asynchronous callbacks get run as part of the "ShouldStop" logic in the thread plan. The logic there is: + // a) If the breakpoint is thread specific and not for this thread, continue w/o running the callback. + // b) If the ignore count says we shouldn't stop, then ditto. + // c) If the condition says we shouldn't stop, then ditto. + // d) Otherwise, the callback will get run, and if it returns true we will stop, and if false we won't. + // The asynchronous callback can run the target itself, but at present that should be the last action the + // callback does. We will relax this condition at some point, but it will take a bit of plumbing to get + // that to work. + // + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Adds a callback to the breakpoint option set. + /// + /// @param[in] callback + /// The function to be called when the breakpoint gets hit. + /// + /// @param[in] baton_sp + /// A baton which will get passed back to the callback when it is invoked. + /// + /// @param[in] synchronous + /// Whether this is a synchronous or asynchronous callback. See discussion above. + //------------------------------------------------------------------ + void SetCallback (BreakpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false); + + + //------------------------------------------------------------------ + /// Remove the callback from this option set. + //------------------------------------------------------------------ + void ClearCallback (); + + // The rest of these functions are meant to be used only within the breakpoint handling mechanism. + + //------------------------------------------------------------------ + /// Use this function to invoke the callback for a specific stop. + /// + /// @param[in] context + /// The context in which the callback is to be invoked. This includes the stop event, the + /// execution context of the stop (since you might hit the same breakpoint on multiple threads) and + /// whether we are currently executing synchronous or asynchronous callbacks. + /// + /// @param[in] break_id + /// The breakpoint ID that owns this option set. + /// + /// @param[in] break_loc_id + /// The breakpoint location ID that owns this option set. + /// + /// @return + /// The callback return value. + //------------------------------------------------------------------ + bool InvokeCallback (StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + //------------------------------------------------------------------ + /// Used in InvokeCallback to tell whether it is the right time to run this kind of callback. + /// + /// @return + /// The synchronicity of our callback. + //------------------------------------------------------------------ + bool IsCallbackSynchronous () { + return m_callback_is_synchronous; + } + + //------------------------------------------------------------------ + /// Fetch the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + Baton *GetBaton (); + + //------------------------------------------------------------------ + /// Fetch a const version of the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + const Baton *GetBaton () const; + + //------------------------------------------------------------------ + // Condition + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Set the breakpoint option's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the breakpoint is hit. + //------------------------------------------------------------------ + void SetCondition (const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or NULL if no + // condition has been set. + //------------------------------------------------------------------ + const char *GetConditionText (size_t *hash = NULL) const; + + //------------------------------------------------------------------ + // Enabled/Ignore Count + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Check the Enable/Disable state. + /// @return + /// \b true if the breakpoint is enabled, \b false if disabled. + //------------------------------------------------------------------ + bool + IsEnabled () const + { + return m_enabled; + } + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false disable it. + //------------------------------------------------------------------ + void + SetEnabled (bool enabled) + { + m_enabled = enabled; + } + + //------------------------------------------------------------------ + /// Check the One-shot state. + /// @return + /// \b true if the breakpoint is one-shot, \b false otherwise. + //------------------------------------------------------------------ + bool + IsOneShot () const + { + return m_one_shot; + } + + //------------------------------------------------------------------ + /// If \a enable is \b true, enable the breakpoint, if \b false disable it. + //------------------------------------------------------------------ + void + SetOneShot (bool one_shot) + { + m_one_shot = one_shot; + } + + //------------------------------------------------------------------ + /// Set the breakpoint to ignore the next \a count breakpoint hits. + /// @param[in] count + /// The number of breakpoint hits to ignore. + //------------------------------------------------------------------ + + void + SetIgnoreCount (uint32_t n) + { + m_ignore_count = n; + } + + //------------------------------------------------------------------ + /// Return the current Ignore Count. + /// @return + /// The number of breakpoint hits to be ignored. + //------------------------------------------------------------------ + uint32_t + GetIgnoreCount () const + { + return m_ignore_count; + } + + //------------------------------------------------------------------ + /// Return the current thread spec for this option. This will return NULL if the no thread + /// specifications have been set for this Option yet. + /// @return + /// The thread specification pointer for this option, or NULL if none has + /// been set yet. + //------------------------------------------------------------------ + const ThreadSpec * + GetThreadSpecNoCreate () const; + + //------------------------------------------------------------------ + /// Returns a pointer to the ThreadSpec for this option, creating it. + /// if it hasn't been created already. This API is used for setting the + /// ThreadSpec items for this option. + //------------------------------------------------------------------ + ThreadSpec * + GetThreadSpec (); + + void + SetThreadID(lldb::tid_t thread_id); + + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Returns true if the breakpoint option has a callback set. + //------------------------------------------------------------------ + bool + HasCallback(); + + //------------------------------------------------------------------ + /// This is the default empty callback. + /// @return + /// The thread id for which the breakpoint hit will stop, + /// LLDB_INVALID_THREAD_ID for all threads. + //------------------------------------------------------------------ + static bool + NullCallback (void *baton, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + + struct CommandData + { + CommandData () : + user_source(), + script_source(), + stop_on_error(true) + { + } + + ~CommandData () + { + } + + StringList user_source; + std::string script_source; + bool stop_on_error; + }; + + class CommandBaton : public Baton + { + public: + CommandBaton (CommandData *data) : + Baton (data) + { + } + + virtual + ~CommandBaton () + { + delete ((CommandData *)m_data); + m_data = NULL; + } + + virtual void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + + }; + +protected: + //------------------------------------------------------------------ + // Classes that inherit from BreakpointOptions can see and modify these + //------------------------------------------------------------------ + +private: + //------------------------------------------------------------------ + // For BreakpointOptions only + //------------------------------------------------------------------ + BreakpointHitCallback m_callback; // This is the callback function pointer + lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback + bool m_callback_is_synchronous; + bool m_enabled; + bool m_one_shot; + uint32_t m_ignore_count; // Number of times to ignore this breakpoint + std::unique_ptr<ThreadSpec> m_thread_spec_ap; // Thread for which this breakpoint will take + std::string m_condition_text; // The condition to test. + size_t m_condition_text_hash; // Its hash, so that locations know when the condition is updated. +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointOptions_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h new file mode 100644 index 0000000..3db3795 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointResolver.h @@ -0,0 +1,147 @@ +//===-- BreakpointResolver.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_BreakpointResolver_h_ +#define liblldb_BreakpointResolver_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Breakpoint/Breakpoint.h" +#include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/RegularExpression.h" +#include "lldb/Core/SearchFilter.h" +#include "lldb/Core/ConstString.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointResolver BreakpointResolver.h "lldb/Breakpoint/BreakpointResolver.h" +/// @brief This class works with SearchFilter to resolve logical breakpoints to their +/// of concrete breakpoint locations. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// The BreakpointResolver is a Searcher. In that protocol, +/// the SearchFilter asks the question "At what depth of the symbol context +/// descent do you want your callback to get called?" of the filter. The resolver +/// answers this question (in the GetDepth method) and provides the resolution callback. +/// Each Breakpoint has a BreakpointResolver, and it calls either ResolveBreakpoint +/// or ResolveBreakpointInModules to tell it to look for new breakpoint locations. +//---------------------------------------------------------------------- + +class BreakpointResolver : + public Searcher +{ +public: + //------------------------------------------------------------------ + /// The breakpoint resolver need to have a breakpoint for "ResolveBreakpoint + /// to make sense. It can be constructed without a breakpoint, but you have to + /// call SetBreakpoint before ResolveBreakpoint. + /// + /// @param[in] bkpt + /// The breakpoint that owns this resolver. + /// @param[in] resolverType + /// The concrete breakpoint resolver type for this breakpoint. + /// + /// @result + /// Returns breakpoint location id. + //------------------------------------------------------------------ + BreakpointResolver (Breakpoint *bkpt, unsigned char resolverType); + + //------------------------------------------------------------------ + /// The Destructor is virtual, all significant breakpoint resolvers derive + /// from this class. + //------------------------------------------------------------------ + virtual + ~BreakpointResolver (); + + //------------------------------------------------------------------ + /// This sets the breakpoint for this resolver. + /// + /// @param[in] bkpt + /// The breakpoint that owns this resolver. + //------------------------------------------------------------------ + void + SetBreakpoint (Breakpoint *bkpt); + + //------------------------------------------------------------------ + /// In response to this method the resolver scans all the modules in the breakpoint's + /// target, and adds any new locations it finds. + /// + /// @param[in] filter + /// The filter that will manage the search for this resolver. + //------------------------------------------------------------------ + virtual void + ResolveBreakpoint (SearchFilter &filter); + + //------------------------------------------------------------------ + /// In response to this method the resolver scans the modules in the module list + /// \a modules, and adds any new locations it finds. + /// + /// @param[in] filter + /// The filter that will manage the search for this resolver. + //------------------------------------------------------------------ + virtual void + ResolveBreakpointInModules (SearchFilter &filter, + ModuleList &modules); + + //------------------------------------------------------------------ + /// Prints a canonical description for the breakpoint to the stream \a s. + /// + /// @param[in] s + /// Stream to which the output is copied. + //------------------------------------------------------------------ + virtual void + GetDescription (Stream *s) = 0; + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + virtual void + Dump (Stream *s) const = 0; + + //------------------------------------------------------------------ + /// An enumeration for keeping track of the concrete subclass that + /// is actually instantiated. Values of this enumeration are kept in the + /// BreakpointResolver's SubclassID field. They are used for concrete type + /// identification. + enum ResolverTy { + FileLineResolver, // This is an instance of BreakpointResolverFileLine + AddressResolver, // This is an instance of BreakpointResolverAddress + NameResolver, // This is an instance of BreakpointResolverName + FileRegexResolver, + ExceptionResolver + }; + + //------------------------------------------------------------------ + /// getResolverID - Return an ID for the concrete type of this object. This + /// is used to implement the LLVM classof checks. This should not be used + /// for any other purpose, as the values may change as LLDB evolves. + unsigned getResolverID() const { + return SubclassID; + } + +protected: + Breakpoint *m_breakpoint; // This is the breakpoint we add locations to. + +private: + // Subclass identifier (for llvm isa/dyn_cast) + const unsigned char SubclassID; + DISALLOW_COPY_AND_ASSIGN(BreakpointResolver); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointResolver_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverAddress.h b/include/lldb/Breakpoint/BreakpointResolverAddress.h new file mode 100644 index 0000000..4ca4a40 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointResolverAddress.h @@ -0,0 +1,74 @@ +//===-- BreakpointResolverAddress.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_BreakpointResolverAddress_h_ +#define liblldb_BreakpointResolverAddress_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointResolver.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointResolverAddress BreakpointResolverAddress.h "lldb/Breakpoint/BreakpointResolverAddress.h" +/// @brief This class sets breakpoints on a given Address. This breakpoint only takes +/// once, and then it won't attempt to reset itself. +//---------------------------------------------------------------------- + +class BreakpointResolverAddress: + public BreakpointResolver +{ +public: + BreakpointResolverAddress (Breakpoint *bkpt, + const Address &addr); + + virtual + ~BreakpointResolverAddress (); + + virtual void + ResolveBreakpoint (SearchFilter &filter); + + virtual void + ResolveBreakpointInModules (SearchFilter &filter, + ModuleList &modules); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + + virtual void + Dump (Stream *s) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverAddress *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::AddressResolver; + } + +protected: + Address m_addr; + +private: + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverAddress); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointResolverAddress_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/include/lldb/Breakpoint/BreakpointResolverFileLine.h new file mode 100644 index 0000000..cc1633c --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -0,0 +1,74 @@ +//===-- BreakpointResolverFileLine.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_BreakpointResolverFileLine_h_ +#define liblldb_BreakpointResolverFileLine_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointResolver.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointResolverFileLine BreakpointResolverFileLine.h "lldb/Breakpoint/BreakpointResolverFileLine.h" +/// @brief This class sets breakpoints by file and line. Optionally, it will look for inlined +/// instances of the file and line specification. +//---------------------------------------------------------------------- + +class BreakpointResolverFileLine : + public BreakpointResolver +{ +public: + BreakpointResolverFileLine (Breakpoint *bkpt, + const FileSpec &resolver, + uint32_t line_no, + bool check_inlines, + bool skip_prologue); + + virtual + ~BreakpointResolverFileLine (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + + virtual void + Dump (Stream *s) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverFileLine *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::FileLineResolver; + } + +protected: + friend class Breakpoint; + FileSpec m_file_spec; // This is the file spec we are looking for. + uint32_t m_line_number; // This is the line number that we are looking for. + bool m_inlines; // This determines whether the resolver looks for inlined functions or not. + bool m_skip_prologue; + +private: + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileLine); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointResolverFileLine_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h new file mode 100644 index 0000000..f1c2b14 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h @@ -0,0 +1,68 @@ +//===-- BreakpointResolverFileRegex.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_BreakpointResolverFileRegex_h_ +#define liblldb_BreakpointResolverFileRegex_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointResolver.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointResolverFileRegex BreakpointResolverFileRegex.h "lldb/Breakpoint/BreakpointResolverFileRegex.h" +/// @brief This class sets breakpoints by file and line. Optionally, it will look for inlined +/// instances of the file and line specification. +//---------------------------------------------------------------------- + +class BreakpointResolverFileRegex : + public BreakpointResolver +{ +public: + BreakpointResolverFileRegex (Breakpoint *bkpt, + RegularExpression ®ex); + + virtual + ~BreakpointResolverFileRegex (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + + virtual void + Dump (Stream *s) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverFileRegex *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::FileRegexResolver; + } + +protected: + friend class Breakpoint; + RegularExpression m_regex; // This is the line expression that we are looking for. + +private: + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileRegex); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointResolverFileRegex_h_ diff --git a/include/lldb/Breakpoint/BreakpointResolverName.h b/include/lldb/Breakpoint/BreakpointResolverName.h new file mode 100644 index 0000000..f481aa9 --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointResolverName.h @@ -0,0 +1,122 @@ +//===-- BreakpointResolverName.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_BreakpointResolverName_h_ +#define liblldb_BreakpointResolverName_h_ + +// C Includes +// C++ Includes +#include <vector> +#include <string> +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointResolver.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointResolverName BreakpointResolverName.h "lldb/Breakpoint/BreakpointResolverName.h" +/// @brief This class sets breakpoints on a given function name, either by exact match +/// or by regular expression. +//---------------------------------------------------------------------- + +class BreakpointResolverName: + public BreakpointResolver +{ +public: + + BreakpointResolverName (Breakpoint *bkpt, + const char *name, + uint32_t name_type_mask, + Breakpoint::MatchType type, + bool skip_prologue); + + // This one takes an array of names. It is always MatchType = Exact. + BreakpointResolverName (Breakpoint *bkpt, + const char *names[], + size_t num_names, + uint32_t name_type_mask, + bool skip_prologue); + + // This one takes a C++ array of names. It is always MatchType = Exact. + BreakpointResolverName (Breakpoint *bkpt, + std::vector<std::string> names, + uint32_t name_type_mask, + bool skip_prologue); + + // Creates a function breakpoint by regular expression. Takes over control of the lifespan of func_regex. + BreakpointResolverName (Breakpoint *bkpt, + RegularExpression &func_regex, + bool skip_prologue); + + BreakpointResolverName (Breakpoint *bkpt, + const char *class_name, + const char *method, + Breakpoint::MatchType type, + bool skip_prologue); + + virtual + ~BreakpointResolverName (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + + virtual void + Dump (Stream *s) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverName *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::NameResolver; + } + +protected: + struct LookupInfo + { + ConstString name; + ConstString lookup_name; + uint32_t name_type_mask; // See FunctionNameType + bool match_name_after_lookup; + + LookupInfo () : + name(), + lookup_name(), + name_type_mask (0), + match_name_after_lookup (false) + { + } + + void + Prune (SymbolContextList &sc_list, + size_t start_idx) const; + }; + std::vector<LookupInfo> m_lookups; + ConstString m_class_name; + RegularExpression m_regex; + Breakpoint::MatchType m_match_type; + bool m_skip_prologue; + + void + AddNameLookup (const ConstString &name, uint32_t name_type_mask); +private: + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverName); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointResolverName_h_ diff --git a/include/lldb/Breakpoint/BreakpointSite.h b/include/lldb/Breakpoint/BreakpointSite.h new file mode 100644 index 0000000..271a23c --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointSite.h @@ -0,0 +1,295 @@ +//===-- BreakpointSite.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_BreakpointSite_h_ +#define liblldb_BreakpointSite_h_ + +// C Includes + +// C++ Includes +#include <list> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/UserID.h" +#include "lldb/Breakpoint/StoppointLocation.h" +#include "lldb/Breakpoint/BreakpointLocationCollection.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointSite BreakpointSite.h "lldb/Breakpoint/BreakpointSite.h" +/// @brief Class that manages the actual breakpoint that will be inserted +/// into the running program. +/// +/// The BreakpointSite class handles the physical breakpoint that is +/// actually inserted in the target program. As such, it is also the +/// one that gets hit, when the program stops. It keeps a list of all +/// BreakpointLocations that share this phsyical site. When the +/// breakpoint is hit, all the locations are informed by the breakpoint +/// site. Breakpoint sites are owned by the process. +//---------------------------------------------------------------------- + +class BreakpointSite : + public std::enable_shared_from_this<BreakpointSite>, + public StoppointLocation +{ +public: + + enum Type + { + eSoftware, // Breakpoint opcode has been written to memory and m_saved_opcode + // and m_trap_opcode contain the saved and written opcode. + eHardware, // Breakpoint site is set as a hardware breakpoint + eExternal // Breakpoint site is managed by an external debug nub or + // debug interface where memory reads trasparently will not + // display any breakpoint opcodes. + }; + + virtual ~BreakpointSite (); + + //---------------------------------------------------------------------- + // This section manages the breakpoint traps + //---------------------------------------------------------------------- + + //------------------------------------------------------------------ + /// Returns the Opcode Bytes for this breakpoint + //------------------------------------------------------------------ + uint8_t * + GetTrapOpcodeBytes (); + + //------------------------------------------------------------------ + /// Returns the Opcode Bytes for this breakpoint - const version + //------------------------------------------------------------------ + const uint8_t * + GetTrapOpcodeBytes () const; + + //------------------------------------------------------------------ + /// Get the size of the trap opcode for this address + //------------------------------------------------------------------ + size_t + GetTrapOpcodeMaxByteSize () const; + + //------------------------------------------------------------------ + /// Sets the trap opcode + //------------------------------------------------------------------ + bool + SetTrapOpcode (const uint8_t *trap_opcode, + uint32_t trap_opcode_size); + + //------------------------------------------------------------------ + /// Gets the original instruction bytes that were overwritten by the trap + //------------------------------------------------------------------ + uint8_t * + GetSavedOpcodeBytes (); + + //------------------------------------------------------------------ + /// Gets the original instruction bytes that were overwritten by the trap const version + //------------------------------------------------------------------ + const uint8_t * + GetSavedOpcodeBytes () const; + + //------------------------------------------------------------------ + /// Says whether \a addr and size \a size intersects with the address \a intersect_addr + //------------------------------------------------------------------ + bool + IntersectsRange (lldb::addr_t addr, + size_t size, + lldb::addr_t *intersect_addr, + size_t *intersect_size, + size_t *opcode_offset) const; + + //------------------------------------------------------------------ + /// Tells whether the current breakpoint site is enabled or not + /// + /// This is a low-level enable bit for the breakpoint sites. If a + /// breakpoint site has no enabled owners, it should just get + /// removed. This enable/disable is for the low-level target code + /// to enable and disable breakpoint sites when single stepping, + /// etc. + //------------------------------------------------------------------ + bool + IsEnabled () const; + + //------------------------------------------------------------------ + /// Sets whether the current breakpoint site is enabled or not + /// + /// @param[in] enabled + /// \b true if the breakoint is enabled, \b false otherwise. + //------------------------------------------------------------------ + void + SetEnabled (bool enabled); + + //------------------------------------------------------------------ + /// Enquires of the breakpoint locations that produced this breakpoint site whether + /// we should stop at this location. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + ShouldStop (StoppointCallbackContext *context); + + //------------------------------------------------------------------ + /// Standard Dump method + /// + /// @param[in] context + /// The stream to dump this output. + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + //------------------------------------------------------------------ + /// The "Owners" are the breakpoint locations that share this + /// breakpoint site. The method adds the \a owner to this breakpoint + /// site's owner list. + /// + /// @param[in] context + /// \a owner is the Breakpoint Location to add. + //------------------------------------------------------------------ + void + AddOwner (const lldb::BreakpointLocationSP &owner); + + //------------------------------------------------------------------ + /// This method returns the number of breakpoint locations currently + /// located at this breakpoint site. + /// + /// @return + /// The number of owners. + //------------------------------------------------------------------ + size_t + GetNumberOfOwners (); + + //------------------------------------------------------------------ + /// This method returns the the breakpoint location at index \a index + /// located at this breakpoint site. The owners are listed ordinally + /// from 0 to GetNumberOfOwners() - 1 so you can use this method to iterate + /// over the owners + /// + /// @param[in] index + /// The index in the list of owners for which you wish the owner location. + /// @return + /// A shared pointer to the breakpoint location at that index. + //------------------------------------------------------------------ + lldb::BreakpointLocationSP + GetOwnerAtIndex (size_t idx); + + //------------------------------------------------------------------ + /// Check whether the owners of this breakpoint site have any + /// thread specifiers, and if yes, is \a thread contained in any + /// of these specifiers. + /// + /// @param[in] thread + /// The thread against which to test. + /// + /// return + /// \b true if the collection contains at least one location that + /// would be valid for this thread, false otherwise. + //------------------------------------------------------------------ + bool + ValidForThisThread (Thread *thread); + + + //------------------------------------------------------------------ + /// Print a description of this breakpoint site to the stream \a s. + /// GetDescription tells you about the breakpoint site's owners. + /// Use BreakpointSite::Dump(Stream *) to get information about the + /// breakpoint site itself. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void + GetDescription (Stream *s, + lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Tell whether a breakpoint has a location at this site. + /// + /// @param[in] bp_id + /// The breakpoint id to query. + /// + /// @result + /// \b true if bp_id has a location that is at this site, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + IsBreakpointAtThisSite (lldb::break_id_t bp_id); + + //------------------------------------------------------------------ + /// Tell whether ALL the breakpoints in the location collection are internal. + /// + /// @result + /// \b true if all breakpoint locations are owned by internal breakpoints, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + IsInternal () const; + + BreakpointSite::Type + GetType () const + { + return m_type; + } + + void + SetType (BreakpointSite::Type type) + { + m_type = type; + } + +private: + friend class Process; + + //------------------------------------------------------------------ + /// The method removes the owner at \a break_loc_id from this breakpoint list. + /// + /// @param[in] context + /// \a break_loc_id is the Breakpoint Location to remove. + //------------------------------------------------------------------ + size_t + RemoveOwner (lldb::break_id_t break_id, + lldb::break_id_t break_loc_id); + + BreakpointSite::Type m_type;///< The type of this breakpoint site. + uint8_t m_saved_opcode[8]; ///< The saved opcode bytes if this breakpoint site uses trap opcodes. + uint8_t m_trap_opcode[8]; ///< The opcode that was used to create the breakpoint if it is a software breakpoint site. + bool m_enabled; ///< Boolean indicating if this breakpoint site enabled or not. + + // Consider adding an optimization where if there is only one + // owner, we don't store a list. The usual case will be only one owner... + BreakpointLocationCollection m_owners; ///< This has the BreakpointLocations that share this breakpoint site. + + static lldb::break_id_t + GetNextID(); + + // Only the Process can create breakpoint sites in + // Process::CreateBreakpointSite (lldb::BreakpointLocationSP &, bool). + BreakpointSite (BreakpointSiteList *list, + const lldb::BreakpointLocationSP& owner, + lldb::addr_t m_addr, + bool use_hardware); + + DISALLOW_COPY_AND_ASSIGN(BreakpointSite); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointSite_h_ diff --git a/include/lldb/Breakpoint/BreakpointSiteList.h b/include/lldb/Breakpoint/BreakpointSiteList.h new file mode 100644 index 0000000..0d4dafc --- /dev/null +++ b/include/lldb/Breakpoint/BreakpointSiteList.h @@ -0,0 +1,216 @@ +//===-- BreakpointSiteList.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_BreakpointSiteList_h_ +#define liblldb_BreakpointSiteList_h_ + +// C Includes +// C++ Includes +#include <map> +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointSite.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointSiteList BreakpointSiteList.h "lldb/Breakpoint/BreakpointSiteList.h" +/// @brief Class that manages lists of BreakpointSite shared pointers. +//---------------------------------------------------------------------- +class BreakpointSiteList +{ +// At present Process directly accesses the map of BreakpointSites so it can +// do quick lookups into the map (using GetMap). +// FIXME: Find a better interface for this. +friend class Process; + +public: + //------------------------------------------------------------------ + /// Default constructor makes an empty list. + //------------------------------------------------------------------ + BreakpointSiteList(); + + //------------------------------------------------------------------ + /// Destructor, currently does nothing. + //------------------------------------------------------------------ + ~BreakpointSiteList(); + + //------------------------------------------------------------------ + /// Add a BreakpointSite to the list. + /// + /// @param[in] bp_site_sp + /// A shared pointer to a breakpoint site being added to the list. + /// + /// @return + /// The ID of the BreakpointSite in the list. + //------------------------------------------------------------------ + lldb::break_id_t + Add (const lldb::BreakpointSiteSP& bp_site_sp); + + //------------------------------------------------------------------ + /// Standard Dump routine, doesn't do anything at present. + /// @param[in] s + /// Stream into which to dump the description. + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint site at address + /// \a addr. + /// + /// @param[in] addr + /// The address to look for. + /// + /// @result + /// A shared pointer to the breakpoint site. May contain a NULL + /// pointer if no breakpoint site exists with a matching address. + //------------------------------------------------------------------ + lldb::BreakpointSiteSP + FindByAddress (lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint site with id \a breakID. + /// + /// @param[in] breakID + /// The breakpoint site ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint site. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + lldb::BreakpointSiteSP + FindByID (lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the breakpoint site with id \a breakID - const version. + /// + /// @param[in] breakID + /// The breakpoint site ID to seek for. + /// + /// @result + /// A shared pointer to the breakpoint site. May contain a NULL pointer if the + /// breakpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::BreakpointSiteSP + FindByID (lldb::break_id_t breakID) const; + + //------------------------------------------------------------------ + /// Returns the breakpoint site id to the breakpoint site at address \a addr. + /// + /// @param[in] addr + /// The address to match. + /// + /// @result + /// The ID of the breakpoint site, or LLDB_INVALID_BREAK_ID. + //------------------------------------------------------------------ + lldb::break_id_t + FindIDByAddress (lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Returns whether the breakpoint site \a bp_site_id has \a bp_id + // as one of its owners. + /// + /// @param[in] bp_site_id + /// The breakpoint site id to query. + /// + /// @param[in] bp_id + /// The breakpoint id to look for in \a bp_site_id. + /// + /// @result + /// True if \a bp_site_id exists in the site list AND \a bp_id is one of the + /// owners of that site. + //------------------------------------------------------------------ + bool + BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id); + + void + ForEach (std::function <void(BreakpointSite *)> const &callback); + + //------------------------------------------------------------------ + /// Removes the breakpoint site given by \b breakID from this list. + /// + /// @param[in] breakID + /// The breakpoint site index to remove. + /// + /// @result + /// \b true if the breakpoint site \a breakID was in the list. + //------------------------------------------------------------------ + bool + Remove (lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Removes the breakpoint site at address \a addr from this list. + /// + /// @param[in] addr + /// The address from which to remove a breakpoint site. + /// + /// @result + /// \b true if \a addr had a breakpoint site to remove from the list. + //------------------------------------------------------------------ + bool + RemoveByAddress (lldb::addr_t addr); + + bool + FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const; + + typedef void (*BreakpointSiteSPMapFunc) (lldb::BreakpointSiteSP &bp, void *baton); + + //------------------------------------------------------------------ + /// Enquires of the breakpoint site on in this list with ID \a breakID whether + /// we should stop for the breakpoint or not. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] breakID + /// This break ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool + ShouldStop (StoppointCallbackContext *context, lldb::break_id_t breakID); + + //------------------------------------------------------------------ + /// Returns the number of elements in the list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t + GetSize() const + { + Mutex::Locker locker(m_mutex); + return m_bp_site_list.size(); + } + + bool + IsEmpty() const + { + Mutex::Locker locker(m_mutex); + return m_bp_site_list.empty(); + } +protected: + typedef std::map<lldb::addr_t, lldb::BreakpointSiteSP> collection; + + collection::iterator + GetIDIterator(lldb::break_id_t breakID); + + collection::const_iterator + GetIDConstIterator(lldb::break_id_t breakID) const; + + mutable Mutex m_mutex; + collection m_bp_site_list; // The breakpoint site list. +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointSiteList_h_ diff --git a/include/lldb/Breakpoint/Stoppoint.h b/include/lldb/Breakpoint/Stoppoint.h new file mode 100644 index 0000000..c294830 --- /dev/null +++ b/include/lldb/Breakpoint/Stoppoint.h @@ -0,0 +1,63 @@ +//===-- Stoppoint.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_Stoppoint_h_ +#define liblldb_Stoppoint_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/UserID.h" + +namespace lldb_private { + +class Stoppoint +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Stoppoint(); + + virtual + ~Stoppoint(); + + //------------------------------------------------------------------ + // Methods + //------------------------------------------------------------------ + virtual void + Dump (Stream *) = 0; + + virtual bool + IsEnabled () = 0; + + virtual void + SetEnabled (bool enable) = 0; + + lldb::break_id_t + GetID () const; + + void + SetID (lldb::break_id_t bid); + +protected: + lldb::break_id_t m_bid; + +private: + //------------------------------------------------------------------ + // For Stoppoint only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (Stoppoint); +}; + +} // namespace lldb_private + +#endif // liblldb_Stoppoint_h_ diff --git a/include/lldb/Breakpoint/StoppointCallbackContext.h b/include/lldb/Breakpoint/StoppointCallbackContext.h new file mode 100644 index 0000000..78327e2 --- /dev/null +++ b/include/lldb/Breakpoint/StoppointCallbackContext.h @@ -0,0 +1,58 @@ +//===-- StoppointCallbackContext.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_StoppointCallbackContext_h_ +#define liblldb_StoppointCallbackContext_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class StoppointCallbackContext StoppointCallbackContext.h "lldb/Breakpoint/StoppointCallbackContext.h" +/// @brief Class holds the information that a breakpoint callback needs to evaluate this stop. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// When we hit a breakpoint we need to package up whatever information is needed +/// to evaluate breakpoint commands and conditions. This class is the container of +/// that information. +//---------------------------------------------------------------------- + +class StoppointCallbackContext +{ +public: + StoppointCallbackContext(); + + StoppointCallbackContext(Event *event, const ExecutionContext &exe_ctx, bool synchronously = false); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the event, process and thread to NULL, and the frame index to an + /// invalid value. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + Event *event; // This is the event, the callback can modify this to indicate + // the meaning of the breakpoint hit + ExecutionContextRef exe_ctx_ref; // This tells us where we have stopped, what thread. + bool is_synchronous; // Is the callback being executed synchronously with the breakpoint, + // or asynchronously as the event is retrieved? +}; + +} // namespace lldb_private + +#endif // liblldb_StoppointCallbackContext_h_ diff --git a/include/lldb/Breakpoint/StoppointLocation.h b/include/lldb/Breakpoint/StoppointLocation.h new file mode 100644 index 0000000..ccedc51 --- /dev/null +++ b/include/lldb/Breakpoint/StoppointLocation.h @@ -0,0 +1,147 @@ +//===-- StoppointLocation.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_StoppointLocation_h_ +#define liblldb_StoppointLocation_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/UserID.h" +// #include "lldb/Breakpoint/BreakpointOptions.h" + +namespace lldb_private { + +class StoppointLocation +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StoppointLocation (lldb::break_id_t bid, + lldb::addr_t m_addr, + bool hardware); + + StoppointLocation (lldb::break_id_t bid, + lldb::addr_t m_addr, + uint32_t byte_size, + bool hardware); + + virtual + ~StoppointLocation (); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + // Methods + //------------------------------------------------------------------ + virtual lldb::addr_t + GetLoadAddress() const + { + return m_addr; + } + + virtual void + SetLoadAddress (lldb::addr_t addr) + { + m_addr = addr; + } + + uint32_t + GetByteSize () const + { + return m_byte_size; + } + + uint32_t + GetHitCount () const + { + return m_hit_count; + } + + uint32_t + GetHardwareIndex () const + { + return m_hw_index; + } + + + bool + HardwarePreferred () const + { + return m_hw_preferred; + } + + virtual bool + IsHardware () const + { + return m_hw_index != LLDB_INVALID_INDEX32; + } + + + virtual bool + ShouldStop (StoppointCallbackContext *context) + { + return true; + } + + virtual void + Dump (Stream *stream) const + { + } + + void + SetHardwareIndex (uint32_t index) + { + m_hw_index = index; + } + + + lldb::break_id_t + GetID () const + { + return m_loc_id; + } + +protected: + //------------------------------------------------------------------ + // Classes that inherit from StoppointLocation can see and modify these + //------------------------------------------------------------------ + lldb::break_id_t m_loc_id; // Stoppoint location ID + lldb::addr_t m_addr; // The load address of this stop point. The base Stoppoint doesn't + // store a full Address since that's not needed for the breakpoint sites. + bool m_hw_preferred; // 1 if this point has been requested to be set using hardware (which may fail due to lack of resources) + uint32_t m_hw_index; // The hardware resource index for this breakpoint/watchpoint + uint32_t m_byte_size; // The size in bytes of stop location. e.g. the length of the trap opcode for + // software breakpoints, or the optional length in bytes for + // hardware breakpoints, or the length of the watchpoint. + uint32_t m_hit_count; // Number of times this breakpoint/watchpoint has been hit + + // If you override this, be sure to call the base class to increment the internal counter. + void + IncrementHitCount () + { + ++m_hit_count; + } + +private: + //------------------------------------------------------------------ + // For StoppointLocation only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(StoppointLocation); + StoppointLocation(); // Disallow default constructor +}; + +} // namespace lldb_private + +#endif // liblldb_StoppointLocation_h_ diff --git a/include/lldb/Breakpoint/Watchpoint.h b/include/lldb/Breakpoint/Watchpoint.h new file mode 100644 index 0000000..5dbed03 --- /dev/null +++ b/include/lldb/Breakpoint/Watchpoint.h @@ -0,0 +1,252 @@ +//===-- Watchpoint.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_Watchpoint_h_ +#define liblldb_Watchpoint_h_ + +// C Includes + +// C++ Includes +#include <list> +#include <string> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/Target.h" +#include "lldb/Core/UserID.h" +#include "lldb/Breakpoint/WatchpointOptions.h" +#include "lldb/Breakpoint/StoppointLocation.h" + +namespace lldb_private { + +class Watchpoint : + public std::enable_shared_from_this<Watchpoint>, + public StoppointLocation +{ +public: + + class WatchpointEventData : + public EventData + { + public: + + static const ConstString & + GetFlavorString (); + + virtual const ConstString & + GetFlavor () const; + + WatchpointEventData (lldb::WatchpointEventType sub_type, + const lldb::WatchpointSP &new_watchpoint_sp); + + virtual + ~WatchpointEventData(); + + lldb::WatchpointEventType + GetWatchpointEventType () const; + + lldb::WatchpointSP & + GetWatchpoint (); + + virtual void + Dump (Stream *s) const; + + static lldb::WatchpointEventType + GetWatchpointEventTypeFromEvent (const lldb::EventSP &event_sp); + + static lldb::WatchpointSP + GetWatchpointFromEvent (const lldb::EventSP &event_sp); + + static const WatchpointEventData * + GetEventDataFromEvent (const Event *event_sp); + + private: + + lldb::WatchpointEventType m_watchpoint_event; + lldb::WatchpointSP m_new_watchpoint_sp; + + DISALLOW_COPY_AND_ASSIGN (WatchpointEventData); + }; + + Watchpoint (Target& target, lldb::addr_t addr, uint32_t size, const ClangASTType *type, bool hardware = true); + ~Watchpoint (); + + void + IncrementFalseAlarmsAndReviseHitCount(); + + bool + IsEnabled () const; + + void + SetEnabled (bool enabled, bool notify = true); + + virtual bool + IsHardware () const; + + virtual bool + ShouldStop (StoppointCallbackContext *context); + + bool WatchpointRead () const; + bool WatchpointWrite () const; + uint32_t GetIgnoreCount () const; + void SetIgnoreCount (uint32_t n); + void SetWatchpointType (uint32_t type, bool notify = true); + void SetDeclInfo (const std::string &str); + std::string GetWatchSpec(); + void SetWatchSpec (const std::string &str); + + // Snapshot management interface. + bool IsWatchVariable() const; + void SetWatchVariable(bool val); + bool CaptureWatchedValue (const ExecutionContext &exe_ctx); + + void GetDescription (Stream *s, lldb::DescriptionLevel level); + void Dump (Stream *s) const; + void DumpSnapshots (Stream *s, const char * prefix = NULL) const; + void DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const; + Target &GetTarget() { return m_target; } + const Error &GetError() { return m_error; } + + //------------------------------------------------------------------ + /// Returns the WatchpointOptions structure set for this watchpoint. + /// + /// @return + /// A pointer to this watchpoint's WatchpointOptions. + //------------------------------------------------------------------ + WatchpointOptions * + GetOptions () { return &m_options; } + + //------------------------------------------------------------------ + /// Set the callback action invoked when the watchpoint is hit. + /// + /// @param[in] callback + /// The method that will get called when the watchpoint is hit. + /// @param[in] callback_baton + /// A void * pointer that will get passed back to the callback function. + /// @param[in] is_synchronous + /// If \b true the callback will be run on the private event thread + /// before the stop event gets reported. If false, the callback will get + /// handled on the public event thead after the stop has been posted. + /// + /// @return + /// \b true if the process should stop when you hit the watchpoint. + /// \b false if it should continue. + //------------------------------------------------------------------ + void + SetCallback (WatchpointHitCallback callback, + void *callback_baton, + bool is_synchronous = false); + + void + SetCallback (WatchpointHitCallback callback, + const lldb::BatonSP &callback_baton_sp, + bool is_synchronous = false); + + void ClearCallback(); + + //------------------------------------------------------------------ + /// Invoke the callback action when the watchpoint is hit. + /// + /// @param[in] context + /// Described the watchpoint event. + /// + /// @return + /// \b true if the target should stop at this watchpoint and \b false not. + //------------------------------------------------------------------ + bool + InvokeCallback (StoppointCallbackContext *context); + + //------------------------------------------------------------------ + // Condition + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Set the watchpoint's condition. + /// + /// @param[in] condition + /// The condition expression to evaluate when the watchpoint is hit. + /// Pass in NULL to clear the condition. + //------------------------------------------------------------------ + void SetCondition (const char *condition); + + //------------------------------------------------------------------ + /// Return a pointer to the text of the condition expression. + /// + /// @return + /// A pointer to the condition expression text, or NULL if no + // condition has been set. + //------------------------------------------------------------------ + const char *GetConditionText () const; + + void + TurnOnEphemeralMode(); + + void + TurnOffEphemeralMode(); + + bool + IsDisabledDuringEphemeralMode(); + + const ClangASTType & + GetClangASTType() + { + return m_type; + } + + +private: + friend class Target; + friend class WatchpointList; + + void ResetHitCount() { m_hit_count = 0; } + + Target &m_target; + bool m_enabled; // Is this watchpoint enabled + bool m_is_hardware; // Is this a hardware watchpoint + bool m_is_watch_variable; // True if set via 'watchpoint set variable'. + bool m_is_ephemeral; // True if the watchpoint is in the ephemeral mode, meaning that it is + // undergoing a pair of temporary disable/enable actions to avoid recursively + // triggering further watchpoint events. + uint32_t m_disabled_count; // Keep track of the count that the watchpoint is disabled while in ephemeral mode. + // At the end of the ephemeral mode when the watchpoint is to be enabled agian, + // we check the count, if it is more than 1, it means the user-supplied actions + // actually want the watchpoint to be disabled! + uint32_t m_watch_read:1, // 1 if we stop when the watched data is read from + m_watch_write:1, // 1 if we stop when the watched data is written to + m_watch_was_read:1, // Set to 1 when watchpoint is hit for a read access + m_watch_was_written:1; // Set to 1 when watchpoint is hit for a write access + uint32_t m_ignore_count; // Number of times to ignore this watchpoint + uint32_t m_false_alarms; // Number of false alarms. + std::string m_decl_str; // Declaration information, if any. + std::string m_watch_spec_str; // Spec for the watchpoint. + lldb::ValueObjectSP m_old_value_sp; + lldb::ValueObjectSP m_new_value_sp; + ClangASTType m_type; + Error m_error; // An error object describing errors associated with this watchpoint. + WatchpointOptions m_options; // Settable watchpoint options, which is a delegate to handle + // the callback machinery. + bool m_being_created; + + std::unique_ptr<ClangUserExpression> m_condition_ap; // The condition to test. + + void SetID(lldb::watch_id_t id) { m_loc_id = id; } + + void + SendWatchpointChangedEvent (lldb::WatchpointEventType eventKind); + + void + SendWatchpointChangedEvent (WatchpointEventData *data); + + DISALLOW_COPY_AND_ASSIGN (Watchpoint); +}; + +} // namespace lldb_private + +#endif // liblldb_Watchpoint_h_ diff --git a/include/lldb/Breakpoint/WatchpointList.h b/include/lldb/Breakpoint/WatchpointList.h new file mode 100644 index 0000000..d16cb25 --- /dev/null +++ b/include/lldb/Breakpoint/WatchpointList.h @@ -0,0 +1,276 @@ +//===-- WatchpointList.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_WatchpointList_h_ +#define liblldb_WatchpointList_h_ + +// C Includes +// C++ Includes +#include <list> +#include <vector> +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class WatchpointList WatchpointList.h "lldb/Breakpoint/WatchpointList.h" +/// @brief This class is used by Watchpoint to manage a list of watchpoints, +// each watchpoint in the list has a unique ID, and is unique by Address as +// well. +//---------------------------------------------------------------------- + +class WatchpointList +{ +// Only Target can make the watchpoint list, or add elements to it. +// This is not just some random collection of watchpoints. Rather, the act of +// adding the watchpoint to this list sets its ID. +friend class Watchpoint; +friend class Target; + +public: + //------------------------------------------------------------------ + /// Default constructor makes an empty list. + //------------------------------------------------------------------ + WatchpointList(); + + //------------------------------------------------------------------ + /// Destructor, currently does nothing. + //------------------------------------------------------------------ + ~WatchpointList(); + + //------------------------------------------------------------------ + /// Add a Watchpoint to the list. + /// + /// @param[in] wp_sp + /// A shared pointer to a watchpoint being added to the list. + /// + /// @return + /// The ID of the Watchpoint in the list. + //------------------------------------------------------------------ + lldb::watch_id_t + Add (const lldb::WatchpointSP& wp_sp, bool notify); + + //------------------------------------------------------------------ + /// Standard "Dump" method. + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + //------------------------------------------------------------------ + /// Dump with lldb::DescriptionLevel. + //------------------------------------------------------------------ + void + DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint at address + /// \a addr - + /// const version. + /// + /// @param[in] addr + /// The address to look for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL + /// pointer if the watchpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::WatchpointSP + FindByAddress (lldb::addr_t addr) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with watchpoint spec + /// \a spec - + /// const version. + /// + /// @param[in] spec + /// The watchpoint spec to look for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL + /// pointer if the watchpoint doesn't exist. + //------------------------------------------------------------------ + const lldb::WatchpointSP + FindBySpec (std::string spec) const; + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with id + /// \a watchID, const + /// version. + /// + /// @param[in] watchID + /// The watchpoint location ID to seek for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL + /// pointer if the watchpoint doesn't exist. + //------------------------------------------------------------------ + lldb::WatchpointSP + FindByID (lldb::watch_id_t watchID) const; + + //------------------------------------------------------------------ + /// Returns the watchpoint id to the watchpoint + /// at address \a addr. + /// + /// @param[in] addr + /// The address to match. + /// + /// @result + /// The ID of the watchpoint, or LLDB_INVALID_WATCH_ID. + //------------------------------------------------------------------ + lldb::watch_id_t + FindIDByAddress (lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Returns the watchpoint id to the watchpoint + /// with watchpoint spec \a spec. + /// + /// @param[in] spec + /// The watchpoint spec to match. + /// + /// @result + /// The ID of the watchpoint, or LLDB_INVALID_WATCH_ID. + //------------------------------------------------------------------ + lldb::watch_id_t + FindIDBySpec (std::string spec); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with index \a i. + /// + /// @param[in] i + /// The watchpoint index to seek for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL pointer if + /// the watchpoint doesn't exist. + //------------------------------------------------------------------ + lldb::WatchpointSP + GetByIndex (uint32_t i); + + //------------------------------------------------------------------ + /// Returns a shared pointer to the watchpoint with index \a i, const + /// version. + /// + /// @param[in] i + /// The watchpoint index to seek for. + /// + /// @result + /// A shared pointer to the watchpoint. May contain a NULL pointer if + /// the watchpoint location doesn't exist. + //------------------------------------------------------------------ + const lldb::WatchpointSP + GetByIndex (uint32_t i) const; + + //------------------------------------------------------------------ + /// Removes the watchpoint given by \b watchID from this list. + /// + /// @param[in] watchID + /// The watchpoint ID to remove. + /// + /// @result + /// \b true if the watchpoint \a watchID was in the list. + //------------------------------------------------------------------ + bool + Remove (lldb::watch_id_t watchID, bool notify); + + //------------------------------------------------------------------ + /// Returns the number hit count of all watchpoints in this list. + /// + /// @result + /// Hit count of all watchpoints in this list. + //------------------------------------------------------------------ + uint32_t + GetHitCount () const; + + //------------------------------------------------------------------ + /// Enquires of the watchpoint in this list with ID \a watchID whether we + /// should stop. + /// + /// @param[in] context + /// This contains the information about this stop. + /// + /// @param[in] watchID + /// This watch ID that we hit. + /// + /// @return + /// \b true if we should stop, \b false otherwise. + //------------------------------------------------------------------ + bool + ShouldStop (StoppointCallbackContext *context, + lldb::watch_id_t watchID); + + //------------------------------------------------------------------ + /// Returns the number of elements in this watchpoint list. + /// + /// @result + /// The number of elements. + //------------------------------------------------------------------ + size_t + GetSize() const + { + Mutex::Locker locker(m_mutex); + return m_watchpoints.size(); + } + + //------------------------------------------------------------------ + /// Print a description of the watchpoints in this list to the stream \a s. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The description level that indicates the detail level to + /// provide. + /// + /// @see lldb::DescriptionLevel + //------------------------------------------------------------------ + void + GetDescription (Stream *s, + lldb::DescriptionLevel level); + + void + SetEnabledAll (bool enabled); + + void + RemoveAll (bool notify); + + //------------------------------------------------------------------ + /// Sets the passed in Locker to hold the Watchpoint List mutex. + /// + /// @param[in] locker + /// The locker object that is set. + //------------------------------------------------------------------ + void + GetListMutex (lldb_private::Mutex::Locker &locker); + +protected: + typedef std::list<lldb::WatchpointSP> wp_collection; + typedef std::vector<lldb::watch_id_t> id_vector; + + id_vector + GetWatchpointIDs() const; + + wp_collection::iterator + GetIDIterator(lldb::watch_id_t watchID); + + wp_collection::const_iterator + GetIDConstIterator(lldb::watch_id_t watchID) const; + + wp_collection m_watchpoints; + mutable Mutex m_mutex; + + lldb::watch_id_t m_next_wp_id; +}; + +} // namespace lldb_private + +#endif // liblldb_WatchpointList_h_ diff --git a/include/lldb/Breakpoint/WatchpointOptions.h b/include/lldb/Breakpoint/WatchpointOptions.h new file mode 100644 index 0000000..64c65f9 --- /dev/null +++ b/include/lldb/Breakpoint/WatchpointOptions.h @@ -0,0 +1,255 @@ +//===-- WatchpointOptions.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_WatchpointOptions_h_ +#define liblldb_WatchpointOptions_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Baton.h" +#include "lldb/Core/StringList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class WatchpointOptions WatchpointOptions.h "lldb/Breakpoint/WatchpointOptions.h" +/// @brief Class that manages the options on a watchpoint. +//---------------------------------------------------------------------- + +class WatchpointOptions +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + //------------------------------------------------------------------ + /// Default constructor. The watchpoint is enabled, and has no condition, + /// callback, ignore count, etc... + //------------------------------------------------------------------ + WatchpointOptions(); + WatchpointOptions(const WatchpointOptions& rhs); + + static WatchpointOptions * + CopyOptionsNoCallback (WatchpointOptions &rhs); + //------------------------------------------------------------------ + /// This constructor allows you to specify all the watchpoint options. + /// + /// @param[in] callback + /// This is the plugin for some code that gets run, returns \b true if we are to stop. + /// + /// @param[in] baton + /// Client data that will get passed to the callback. + /// + /// @param[in] thread_id + /// Only stop if \a thread_id hits the watchpoint. + //------------------------------------------------------------------ + WatchpointOptions(WatchpointHitCallback callback, + void *baton, + lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID); + + virtual ~WatchpointOptions(); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const WatchpointOptions& + operator=(const WatchpointOptions& rhs); + + //------------------------------------------------------------------ + // Callbacks + // + // Watchpoint callbacks come in two forms, synchronous and asynchronous. Synchronous callbacks will get + // run before any of the thread plans are consulted, and if they return false the target will continue + // "under the radar" of the thread plans. There are a couple of restrictions to synchronous callbacks: + // 1) They should NOT resume the target themselves. Just return false if you want the target to restart. + // 2) Watchpoints with synchronous callbacks can't have conditions (or rather, they can have them, but they + // won't do anything. Ditto with ignore counts, etc... You are supposed to control that all through the + // callback. + // Asynchronous callbacks get run as part of the "ShouldStop" logic in the thread plan. The logic there is: + // a) If the watchpoint is thread specific and not for this thread, continue w/o running the callback. + // b) If the ignore count says we shouldn't stop, then ditto. + // c) If the condition says we shouldn't stop, then ditto. + // d) Otherwise, the callback will get run, and if it returns true we will stop, and if false we won't. + // The asynchronous callback can run the target itself, but at present that should be the last action the + // callback does. We will relax this condition at some point, but it will take a bit of plumbing to get + // that to work. + // + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Adds a callback to the watchpoint option set. + /// + /// @param[in] callback + /// The function to be called when the watchpoint gets hit. + /// + /// @param[in] baton_sp + /// A baton which will get passed back to the callback when it is invoked. + /// + /// @param[in] synchronous + /// Whether this is a synchronous or asynchronous callback. See discussion above. + //------------------------------------------------------------------ + void SetCallback (WatchpointHitCallback callback, const lldb::BatonSP &baton_sp, bool synchronous = false); + + + //------------------------------------------------------------------ + /// Remove the callback from this option set. + //------------------------------------------------------------------ + void ClearCallback (); + + // The rest of these functions are meant to be used only within the watchpoint handling mechanism. + + //------------------------------------------------------------------ + /// Use this function to invoke the callback for a specific stop. + /// + /// @param[in] context + /// The context in which the callback is to be invoked. This includes the stop event, the + /// execution context of the stop (since you might hit the same watchpoint on multiple threads) and + /// whether we are currently executing synchronous or asynchronous callbacks. + /// + /// @param[in] watch_id + /// The watchpoint ID that owns this option set. + /// + /// @return + /// The callback return value. + //------------------------------------------------------------------ + bool InvokeCallback (StoppointCallbackContext *context, lldb::user_id_t watch_id); + + //------------------------------------------------------------------ + /// Used in InvokeCallback to tell whether it is the right time to run this kind of callback. + /// + /// @return + /// The synchronicity of our callback. + //------------------------------------------------------------------ + bool IsCallbackSynchronous () { + return m_callback_is_synchronous; + } + + //------------------------------------------------------------------ + /// Fetch the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + Baton *GetBaton (); + + //------------------------------------------------------------------ + /// Fetch a const version of the baton from the callback. + /// + /// @return + /// The baton. + //------------------------------------------------------------------ + const Baton *GetBaton () const; + + //------------------------------------------------------------------ + /// Return the current thread spec for this option. This will return NULL if the no thread + /// specifications have been set for this Option yet. + /// @return + /// The thread specification pointer for this option, or NULL if none has + /// been set yet. + //------------------------------------------------------------------ + const ThreadSpec * + GetThreadSpecNoCreate () const; + + //------------------------------------------------------------------ + /// Returns a pointer to the ThreadSpec for this option, creating it. + /// if it hasn't been created already. This API is used for setting the + /// ThreadSpec items for this option. + //------------------------------------------------------------------ + ThreadSpec * + GetThreadSpec (); + + void + SetThreadID(lldb::tid_t thread_id); + + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Get description for callback only. + //------------------------------------------------------------------ + void + GetCallbackDescription (Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Returns true if the watchpoint option has a callback set. + //------------------------------------------------------------------ + bool + HasCallback(); + + //------------------------------------------------------------------ + /// This is the default empty callback. + /// @return + /// The thread id for which the watchpoint hit will stop, + /// LLDB_INVALID_THREAD_ID for all threads. + //------------------------------------------------------------------ + static bool + NullCallback (void *baton, + StoppointCallbackContext *context, + lldb::user_id_t watch_id); + + + struct CommandData + { + CommandData () : + user_source(), + script_source(), + stop_on_error(true) + { + } + + ~CommandData () + { + } + + StringList user_source; + std::string script_source; + bool stop_on_error; + }; + + class CommandBaton : public Baton + { + public: + CommandBaton (CommandData *data) : + Baton (data) + { + } + + virtual + ~CommandBaton () + { + delete ((CommandData *)m_data); + m_data = NULL; + } + + virtual void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + + }; + +protected: + //------------------------------------------------------------------ + // Classes that inherit from WatchpointOptions can see and modify these + //------------------------------------------------------------------ + +private: + //------------------------------------------------------------------ + // For WatchpointOptions only + //------------------------------------------------------------------ + WatchpointHitCallback m_callback; // This is the callback function pointer + lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback + bool m_callback_is_synchronous; + std::unique_ptr<ThreadSpec> m_thread_spec_ap; // Thread for which this watchpoint will take +}; + +} // namespace lldb_private + +#endif // liblldb_WatchpointOptions_h_ diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h new file mode 100644 index 0000000..60cd4a8 --- /dev/null +++ b/include/lldb/Core/Address.h @@ -0,0 +1,570 @@ +//===-- Address.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_Address_h_ +#define liblldb_Address_h_ + +// C Includes +// C++ Includes +#include <atomic> +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Symbol/SymbolContextScope.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Address Address.h "lldb/Core/Address.h" +/// @brief A section + offset based address class. +/// +/// The Address 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: +/// @li file addresses +/// @li load addresses +/// +/// File addresses represent 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 represent 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. +//---------------------------------------------------------------------- +class Address +{ +public: + //------------------------------------------------------------------ + /// Dump styles allow the Address::Dump(Stream *,DumpStyle) const + /// function to display Address contents in a variety of ways. + //------------------------------------------------------------------ + typedef enum { + DumpStyleInvalid, ///< Invalid dump style + DumpStyleSectionNameOffset, ///< Display as the section name + offset. + ///< \code + /// // address for printf in libSystem.B.dylib as a section name + offset + /// libSystem.B.dylib.__TEXT.__text + 0x0005cfdf + /// \endcode + DumpStyleSectionPointerOffset, ///< Display as the section pointer + offset (debug output). + ///< \code + /// // address for printf in libSystem.B.dylib as a section pointer + offset + /// (lldb::Section *)0x35cc50 + 0x000000000005cfdf \endcode + DumpStyleFileAddress, ///< Display as the file address (if any). + ///< \code + /// // address for printf in libSystem.B.dylib as a file address + /// 0x000000000005dcff \endcode + DumpStyleModuleWithFileAddress, ///< Display as the file address with the module name prepended (if any). + ///< \code + /// // address for printf in libSystem.B.dylib as a file address + /// libSystem.B.dylib[0x000000000005dcff] \endcode + DumpStyleLoadAddress, ///< Display as the load address (if resolved). + ///< \code + /// // address for printf in libSystem.B.dylib as a load address + /// 0x00007fff8306bcff \endcode + DumpStyleResolvedDescription, ///< Display the details about what an address resolves to. This can + ///< be anything from a symbol context summary (module, function/symbol, + ///< and file and line), to information about what the pointer points to + ///< if the address is in a section (section of pointers, c strings, etc). + DumpStyleResolvedDescriptionNoModule, + DumpStyleDetailedSymbolContext, ///< Detailed symbol context information for an address for all symbol + ///< context members. + DumpStyleResolvedPointerDescription ///< Dereference a pointer at the current address and then lookup the + ///< dereferenced address using DumpStyleResolvedDescription + } DumpStyle; + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize with a invalid section (NULL) and an invalid + /// offset (LLDB_INVALID_ADDRESS). + //------------------------------------------------------------------ + Address () : + m_section_wp (), + m_offset (LLDB_INVALID_ADDRESS) + { + } + + + //------------------------------------------------------------------ + /// Copy constructor + /// + /// Makes a copy of the another Address object \a rhs. + /// + /// @param[in] rhs + /// A const Address object reference to copy. + //------------------------------------------------------------------ + Address (const Address& rhs) : + m_section_wp (rhs.m_section_wp), + m_offset(rhs.m_offset.load()) + { + } + + //------------------------------------------------------------------ + /// Construct with a section pointer and offset. + /// + /// Initialize the address with the supplied \a section and \a + /// offset. + /// + /// @param[in] section + /// A section pointer to a valid lldb::Section, or NULL if the + /// address doesn't have a section or will get resolved later. + /// + /// @param[in] offset + /// The offset in bytes into \a section. + //------------------------------------------------------------------ + Address (const lldb::SectionSP §ion_sp, lldb::addr_t offset) : + m_section_wp (), // Don't init with section_sp in case section_sp is invalid (the weak_ptr will throw) + m_offset (offset) + { + if (section_sp) + m_section_wp = section_sp; + } + + //------------------------------------------------------------------ + /// Construct with a virtual address and section list. + /// + /// Initialize and resolve the address with the supplied virtual + /// address \a file_addr. + /// + /// @param[in] file_addr + /// A virtual file address. + /// + /// @param[in] section_list + /// A list of sections, one of which may contain the \a file_addr. + //------------------------------------------------------------------ + Address (lldb::addr_t file_addr, const SectionList * section_list); + + Address (lldb::addr_t abs_addr); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// Copies the address value from another Address object \a rhs + /// into \a this object. + /// + /// @param[in] rhs + /// A const Address object reference to copy. + /// + /// @return + /// A const Address object reference to \a this. + //------------------------------------------------------------------ +#ifndef SWIG + const Address& + operator= (const Address& rhs); +#endif + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the section to an invalid value (NULL) and an invalid + /// offset (LLDB_INVALID_ADDRESS). + //------------------------------------------------------------------ + void + Clear () + { + m_section_wp.reset(); + m_offset = LLDB_INVALID_ADDRESS; + } + + //------------------------------------------------------------------ + /// Compare two Address objects. + /// + /// @param[in] lhs + /// The Left Hand Side const Address object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const Address object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + CompareFileAddress (const Address& lhs, const Address& rhs); + + static int + CompareLoadAddress (const Address& lhs, const Address& rhs, Target *target); + + static int + CompareModulePointerAndOffset (const Address& lhs, const Address& rhs); + + // For use with std::map, std::multi_map + class ModulePointerAndOffsetLessThanFunctionObject + { + public: + ModulePointerAndOffsetLessThanFunctionObject () {} + + bool + operator() (const Address& a, const Address& b) const + { + return Address::CompareModulePointerAndOffset(a, b) < 0; + } + }; + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. There are many ways to display a section + /// offset based address, and \a style lets the user choose. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] style + /// The display style for the address. + /// + /// @param[in] fallback_style + /// The display style for the address. + /// + /// @return + /// Returns \b true if the address was able to be displayed. + /// File and load addresses may be unresolved and it may not be + /// possible to display a valid value, \b false will be returned + /// in such cases. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ + bool + Dump (Stream *s, + ExecutionContextScope *exe_scope, + DumpStyle style, + DumpStyle fallback_style = DumpStyleInvalid, + uint32_t addr_byte_size = UINT32_MAX) const; + + lldb::AddressClass + GetAddressClass () const; + + //------------------------------------------------------------------ + /// Get the file address. + /// + /// If an address comes from a file on disk that has section + /// relative addresses, then it has a virtual address that is + /// relative to unique section in the object file. + /// + /// @return + /// The valid file virtual address, or LLDB_INVALID_ADDRESS if + /// the address doesn't have a file virtual address (image is + /// from memory only with no representation on disk). + //------------------------------------------------------------------ + lldb::addr_t + GetFileAddress () const; + + //------------------------------------------------------------------ + /// Get the load address. + /// + /// If an address comes from a file on disk that has section + /// relative addresses, then it has a virtual address that is + /// relative to unique section in the object file. Sections get + /// resolved at runtime by DynamicLoader plug-ins as images + /// (executables and shared libraries) get loaded/unloaded. If a + /// section is loaded, then the load address can be resolved. + /// + /// @return + /// The valid load virtual address, or LLDB_INVALID_ADDRESS if + /// the address is currently not loaded. + //------------------------------------------------------------------ + lldb::addr_t + GetLoadAddress (Target *target) const; + + //------------------------------------------------------------------ + /// Get the load address as a callable code load address. + /// + /// This function will first resolve its address to a load address. + /// Then, if the address turns out to be in code address, return the + /// load address that would be required to call or return to. The + /// address might have extra bits set (bit zero will be set to Thumb + /// functions for an ARM target) that are required when changing the + /// program counter to setting a return address. + /// + /// @return + /// The valid load virtual address, or LLDB_INVALID_ADDRESS if + /// the address is currently not loaded. + //------------------------------------------------------------------ + lldb::addr_t + GetCallableLoadAddress (Target *target, bool is_indirect = false) const; + + //------------------------------------------------------------------ + /// Get the load address as an opcode load address. + /// + /// This function will first resolve its address to a load address. + /// Then, if the address turns out to be in code address, return the + /// load address for a an opcode. This address object might have + /// extra bits set (bit zero will be set to Thumb functions for an + /// ARM target) that are required for changing the program counter + /// and this function will remove any bits that are intended for + /// these special purposes. The result of this function can be used + /// to safely write a software breakpoint trap to memory. + /// + /// @return + /// The valid load virtual address with extra callable bits + /// removed, or LLDB_INVALID_ADDRESS if the address is currently + /// not loaded. + //------------------------------------------------------------------ + lldb::addr_t + GetOpcodeLoadAddress (Target *target) const; + + //------------------------------------------------------------------ + /// Get the section relative offset value. + /// + /// @return + /// The current offset, or LLDB_INVALID_ADDRESS if this address + /// doesn't contain a valid offset. + //------------------------------------------------------------------ + lldb::addr_t + GetOffset () const { return m_offset; } + + //------------------------------------------------------------------ + /// Check if an address is section offset. + /// + /// When converting a virtual file or load address into a section + /// offset based address, we often need to know if, given a section + /// list, if the address was able to be converted to section offset. + /// This function returns true if the current value contained in + /// this object is section offset based. + /// + /// @return + /// Returns \b true if the address has a valid section and + /// offset, \b false otherwise. + //------------------------------------------------------------------ + bool + IsSectionOffset() const + { + return IsValid() && (GetSection().get() != NULL); + } + + //------------------------------------------------------------------ + /// Check if the object state is valid. + /// + /// A valid Address object contains either a section pointer and + /// and offset (for section offset based addresses), or just a valid + /// offset (for absolute addresses that have no section). + /// + /// @return + /// Returns \b true if the the offset is valid, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + IsValid() const + { + return m_offset != LLDB_INVALID_ADDRESS; + } + + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + //------------------------------------------------------------------ + size_t + MemorySize () const; + + //------------------------------------------------------------------ + /// Resolve a file virtual address using a section list. + /// + /// Given a list of sections, attempt to resolve \a addr as a + /// an offset into one of the file sections. + /// + /// @return + /// Returns \b true if \a addr was able to be resolved, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + ResolveAddressUsingFileSections (lldb::addr_t addr, const SectionList *sections); + + //------------------------------------------------------------------ + /// Set the address to represent \a load_addr. + /// + /// The address will attempt to find a loaded section within + /// \a target that contains \a load_addr. If successful, this + /// address object will have a valid section and offset. Else this + /// address object will have no section (NULL) and the offset will + /// be \a load_addr. + /// + /// @param[in] load_addr + /// A load address from a current process. + /// + /// @param[in] target + /// The target to use when trying resolve the address into + /// a section + offset. The Target's SectionLoadList object + /// is used to resolve the address. + /// + /// @return + /// Returns \b true if the load address was resolved to be + /// section/offset, \b false otherwise. It is often ok for an + /// address no not resolve to a section in a module, this often + /// happens for JIT'ed code, or any load addresses on the stack + /// or heap. + //------------------------------------------------------------------ + bool + SetLoadAddress (lldb::addr_t load_addr, Target *target); + + bool + SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target); + + bool + SetCallableLoadAddress (lldb::addr_t load_addr, Target *target); + + //------------------------------------------------------------------ + /// Get accessor for the module for this address. + /// + /// @return + /// Returns the Module pointer that this address is an offset + /// in, or NULL if this address doesn't belong in a module, or + /// isn't resolved yet. + //------------------------------------------------------------------ + lldb::ModuleSP + GetModule () const; + + //------------------------------------------------------------------ + /// Get const accessor for the section. + /// + /// @return + /// Returns the const lldb::Section pointer that this address is an + /// offset in, or NULL if this address is absolute. + //------------------------------------------------------------------ + lldb::SectionSP + GetSection () const { return m_section_wp.lock(); } + + //------------------------------------------------------------------ + /// Set accessor for the offset. + /// + /// @param[in] offset + /// A new offset value for this object. + /// + /// @return + /// Returns \b true if the offset changed, \b false otherwise. + //------------------------------------------------------------------ + bool + SetOffset (lldb::addr_t offset) + { + bool changed = m_offset != offset; + m_offset = offset; + return changed; + } + + void + SetRawAddress (lldb::addr_t addr) + { + m_section_wp.reset(); + m_offset = addr; + } + + bool + Slide (int64_t offset) + { + if (m_offset != LLDB_INVALID_ADDRESS) + { + m_offset += offset; + return true; + } + return false; + } + + //------------------------------------------------------------------ + /// Set accessor for the section. + /// + /// @param[in] section + /// A new lldb::Section pointer to use as the section base. Can + /// be NULL for absolute addresses that are not relative to + /// any section. + //------------------------------------------------------------------ + void + SetSection (const lldb::SectionSP §ion_sp) + { + m_section_wp = section_sp; + } + + void + ClearSection () + { + m_section_wp.reset(); + } + //------------------------------------------------------------------ + /// Reconstruct a symbol context from an address. + /// + /// This class doesn't inherit from SymbolContextScope because many + /// address objects have short lifespans. Address objects that are + /// section offset can reconstruct their symbol context by looking + /// up the address in the module found in the section. + /// + /// @see SymbolContextScope::CalculateSymbolContext(SymbolContext*) + //------------------------------------------------------------------ + uint32_t + CalculateSymbolContext (SymbolContext *sc, + uint32_t resolve_scope = lldb::eSymbolContextEverything) const; + + lldb::ModuleSP + CalculateSymbolContextModule () const; + + CompileUnit * + CalculateSymbolContextCompileUnit () const; + + Function * + CalculateSymbolContextFunction () const; + + Block * + CalculateSymbolContextBlock () const; + + Symbol * + CalculateSymbolContextSymbol () const; + + bool + CalculateSymbolContextLineEntry (LineEntry &line_entry) const; + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + lldb::SectionWP m_section_wp; ///< The section for the address, can be NULL. + std::atomic<lldb::addr_t> m_offset; ///< Offset into section if \a m_section_wp is valid... +}; + + +//---------------------------------------------------------------------- +// NOTE: Be careful using this operator. It can correctly compare two +// addresses from the same Module correctly. It can't compare two +// addresses from different modules in any meaningful way, but it will +// compare the module pointers. +// +// To sum things up: +// - works great for addresses within the same module +// - it works for addresses across multiple modules, but don't expect the +// address results to make much sense +// +// This basically lets Address objects be used in ordered collection +// classes. +//---------------------------------------------------------------------- +bool operator< (const Address& lhs, const Address& rhs); +bool operator> (const Address& lhs, const Address& rhs); + + + +bool operator== (const Address& lhs, const Address& rhs); +bool operator!= (const Address& lhs, const Address& rhs); + +} // namespace lldb_private + +#endif // liblldb_Address_h_ diff --git a/include/lldb/Core/AddressRange.h b/include/lldb/Core/AddressRange.h new file mode 100644 index 0000000..bd3ab2a --- /dev/null +++ b/include/lldb/Core/AddressRange.h @@ -0,0 +1,284 @@ +//===-- AddressRange.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_AddressRange_h_ +#define liblldb_AddressRange_h_ + +#include "lldb/Core/Address.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class AddressRange AddressRange.h "lldb/Core/AddressRange.h" +/// @brief A section + offset based address range class. +//---------------------------------------------------------------------- +class AddressRange +{ +public: + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize with a invalid section (NULL), an invalid + /// offset (LLDB_INVALID_ADDRESS), and zero byte size. + //------------------------------------------------------------------ + AddressRange (); + + //------------------------------------------------------------------ + /// Construct with a section pointer, offset, and byte_size. + /// + /// Initialize the address with the supplied \a section, \a + /// offset and \a byte_size. + /// + /// @param[in] section + /// A section pointer to a valid lldb::Section, or NULL if the + /// address doesn't have a section or will get resolved later. + /// + /// @param[in] offset + /// The offset in bytes into \a section. + /// + /// @param[in] byte_size + /// The size in bytes of the address range. + //------------------------------------------------------------------ + AddressRange (const lldb::SectionSP §ion, lldb::addr_t offset, lldb::addr_t byte_size); + + //------------------------------------------------------------------ + /// Construct with a virtual address, section list and byte size. + /// + /// Initialize and resolve the address with the supplied virtual + /// address \a file_addr, and byte size \a byte_size. + /// + /// @param[in] file_addr + /// A virtual address. + /// + /// @param[in] byte_size + /// The size in bytes of the address range. + /// + /// @param[in] section_list + /// A list of sections, one of which may contain the \a vaddr. + //------------------------------------------------------------------ + AddressRange (lldb::addr_t file_addr, lldb::addr_t byte_size, const SectionList *section_list = NULL); + + //------------------------------------------------------------------ + /// Construct with a Address object address and byte size. + /// + /// Initialize by copying the section offset address in \a so_addr, + /// and setting the byte size to \a byte_size. + /// + /// @param[in] so_addr + /// A section offset address object. + /// + /// @param[in] byte_size + /// The size in bytes of the address range. + //------------------------------------------------------------------ + AddressRange (const Address& so_addr, lldb::addr_t byte_size); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual in case this class is subclassed. + //------------------------------------------------------------------ + ~AddressRange (); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the section to an invalid value (NULL), an invalid offset + /// (LLDB_INVALID_ADDRESS) and a zero byte size. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Check if a section offset address is contained in this range. + /// + /// @param[in] so_addr + /// A section offset address object reference. + /// + /// @return + /// Returns \b true if \a so_addr is contained in this range, + /// \b false otherwise. + //------------------------------------------------------------------ +// bool +// Contains (const Address &so_addr) const; + + //------------------------------------------------------------------ + /// Check if a section offset address is contained in this range. + /// + /// @param[in] so_addr_ptr + /// A section offset address object pointer. + /// + /// @return + /// Returns \b true if \a so_addr is contained in this range, + /// \b false otherwise. + //------------------------------------------------------------------ +// bool +// Contains (const Address *so_addr_ptr) const; + + //------------------------------------------------------------------ + /// Check if a section offset \a so_addr when represented as a file + /// address is contained within this object's file address range. + /// + /// @param[in] so_addr + /// A section offset address object reference. + /// + /// @return + /// Returns \b true if both \a this and \a so_addr have + /// resolvable file address values and \a so_addr is contained + /// in the address range, \b false otherwise. + //------------------------------------------------------------------ + bool + ContainsFileAddress (const Address &so_addr) const; + + //------------------------------------------------------------------ + /// Check if the resolved file address \a file_addr is contained + /// within this object's file address range. + /// + /// @param[in] so_addr + /// A section offset address object reference. + /// + /// @return + /// Returns \b true if both \a this has a resolvable file + /// address value and \a so_addr is contained in the address + /// range, \b false otherwise. + //------------------------------------------------------------------ + bool + ContainsFileAddress (lldb::addr_t file_addr) const; + + //------------------------------------------------------------------ + /// Check if a section offset \a so_addr when represented as a load + /// address is contained within this object's load address range. + /// + /// @param[in] so_addr + /// A section offset address object reference. + /// + /// @return + /// Returns \b true if both \a this and \a so_addr have + /// resolvable load address values and \a so_addr is contained + /// in the address range, \b false otherwise. + //------------------------------------------------------------------ + bool + ContainsLoadAddress (const Address &so_addr, Target *target) const; + + //------------------------------------------------------------------ + /// Check if the resolved load address \a load_addr is contained + /// within this object's load address range. + /// + /// @param[in] so_addr + /// A section offset address object reference. + /// + /// @return + /// Returns \b true if both \a this has a resolvable load + /// address value and \a so_addr is contained in the address + /// range, \b false otherwise. + //------------------------------------------------------------------ + bool + ContainsLoadAddress (lldb::addr_t load_addr, Target *target) const; + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. There are many ways to display a section + /// offset based address range, and \a style lets the user choose + /// how the base address gets displayed. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] style + /// The display style for the address. + /// + /// @return + /// Returns \b true if the address was able to be displayed. + /// File and load addresses may be unresolved and it may not be + /// possible to display a valid value, \b false will be returned + /// in such cases. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ + bool + Dump (Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style = Address::DumpStyleInvalid) const; + + //------------------------------------------------------------------ + /// Dump a debug description of this object to a Stream. + /// + /// Dump a debug description of the contents of this object to the + /// supplied stream \a s. + /// + /// The debug description contains verbose internal state such + /// and pointer values, reference counts, etc. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + DumpDebug (Stream *s) const; + + //------------------------------------------------------------------ + /// Get accessor for the base address of the range. + /// + /// @return + /// A reference to the base address object. + //------------------------------------------------------------------ + Address & + GetBaseAddress() { return m_base_addr; } + + //------------------------------------------------------------------ + /// Get const accessor for the base address of the range. + /// + /// @return + /// A const reference to the base address object. + //------------------------------------------------------------------ + const Address & + GetBaseAddress() const { return m_base_addr; } + + //------------------------------------------------------------------ + /// Get accessor for the byte size of this range. + /// + /// @return + /// The size in bytes of this address range. + //------------------------------------------------------------------ + lldb::addr_t + GetByteSize () const { return m_byte_size; } + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + //------------------------------------------------------------------ + size_t + MemorySize () const { + // Noting special for the memory size of a single AddressRange object, + // it is just the size of itself. + return sizeof(AddressRange); + } + + //------------------------------------------------------------------ + /// Set accessor for the byte size of this range. + /// + /// @param[in] byte_size + /// The new size in bytes of this address range. + //------------------------------------------------------------------ + void + SetByteSize (lldb::addr_t byte_size) { m_byte_size = byte_size; } + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + Address m_base_addr; ///< The section offset base address of this range. + lldb::addr_t m_byte_size; ///< The size in bytes of this address range. +}; + +//bool operator== (const AddressRange& lhs, const AddressRange& rhs); + +} // namespace lldb_private + +#endif // liblldb_AddressRange_h_ diff --git a/include/lldb/Core/AddressResolver.h b/include/lldb/Core/AddressResolver.h new file mode 100644 index 0000000..e5fe276 --- /dev/null +++ b/include/lldb/Core/AddressResolver.h @@ -0,0 +1,89 @@ +//===-- AddressResolver.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_AddressResolver_h_ +#define liblldb_AddressResolver_h_ + +#include <vector> + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/SearchFilter.h" +#include "lldb/Core/ConstString.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class AddressResolver AddressResolver.h "lldb/Core/AddressResolver.h" +/// @brief This class works with SearchFilter to resolve function names and +/// source file locations to their concrete addresses. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// The AddressResolver is a Searcher. In that protocol, +/// the SearchFilter asks the question "At what depth of the symbol context +/// descent do you want your callback to get called?" of the filter. The resolver +/// answers this question (in the GetDepth method) and provides the resolution callback. +//---------------------------------------------------------------------- + +class AddressResolver : + public Searcher +{ +public: + + typedef enum + { + Exact, + Regexp, + Glob + } MatchType; + + + AddressResolver (); + + virtual + ~AddressResolver (); + + virtual void + ResolveAddress (SearchFilter &filter); + + virtual void + ResolveAddressInModules (SearchFilter &filter, + ModuleList &modules); + + virtual void + GetDescription (Stream *s) = 0; + + std::vector<AddressRange> & + GetAddressRanges (); + + size_t + GetNumberOfAddresses (); + + AddressRange & + GetAddressRangeAtIndex (size_t idx); + +protected: + + std::vector<AddressRange> m_address_ranges; + +private: + DISALLOW_COPY_AND_ASSIGN(AddressResolver); +}; + +} // namespace lldb_private + +#endif // liblldb_AddressResolver_h_ diff --git a/include/lldb/Core/AddressResolverFileLine.h b/include/lldb/Core/AddressResolverFileLine.h new file mode 100644 index 0000000..ddeb0e0 --- /dev/null +++ b/include/lldb/Core/AddressResolverFileLine.h @@ -0,0 +1,59 @@ +//===-- AddressResolverFileLine.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_AddressResolverFileLine_h_ +#define liblldb_AddressResolverFileLine_h_ + +// Project includes +#include "lldb/Core/AddressResolver.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class AddressResolverFileLine AddressResolverFileLine.h "lldb/Core/AddressResolverFileLine.h" +/// @brief This class finds address for source file and line. Optionally, it will look for inlined +/// instances of the file and line specification. +//---------------------------------------------------------------------- + +class AddressResolverFileLine : + public AddressResolver +{ +public: + + AddressResolverFileLine (const FileSpec &resolver, + uint32_t line_no, + bool check_inlines); + + virtual + ~AddressResolverFileLine (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + +protected: + FileSpec m_file_spec; // This is the file spec we are looking for. + uint32_t m_line_number; // This is the line number that we are looking for. + bool m_inlines; // This determines whether the resolver looks for inlined functions or not. + +private: + DISALLOW_COPY_AND_ASSIGN(AddressResolverFileLine); +}; + +} // namespace lldb_private + +#endif // liblldb_AddressResolverFileLine_h_ diff --git a/include/lldb/Core/AddressResolverName.h b/include/lldb/Core/AddressResolverName.h new file mode 100644 index 0000000..afde675 --- /dev/null +++ b/include/lldb/Core/AddressResolverName.h @@ -0,0 +1,68 @@ +//===-- AddressResolverName.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_AddressResolverName_h_ +#define liblldb_AddressResolverName_h_ + +// Project includes + +#include "lldb/Core/AddressResolver.h" +#include "lldb/Core/RegularExpression.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class AddressResolverName AddressResolverName.h "lldb/Core/AddressResolverName.h" +/// @brief This class finds addresses for a given function name, either by exact match +/// or by regular expression. +//---------------------------------------------------------------------- + +class AddressResolverName: + public AddressResolver +{ +public: + + AddressResolverName (const char *func_name, + AddressResolver::MatchType type = Exact); + + // Creates a function breakpoint by regular expression. Takes over control of the lifespan of func_regex. + AddressResolverName (RegularExpression &func_regex); + + AddressResolverName (const char *class_name, + const char *method, + AddressResolver::MatchType type); + + virtual + ~AddressResolverName (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + +protected: + ConstString m_func_name; + ConstString m_class_name; // FIXME: Not used yet. The idea would be to stop on methods of this class. + RegularExpression m_regex; + AddressResolver::MatchType m_match_type; + +private: + DISALLOW_COPY_AND_ASSIGN(AddressResolverName); +}; + +} // namespace lldb_private + +#endif // liblldb_AddressResolverName_h_ diff --git a/include/lldb/Core/ArchSpec.h b/include/lldb/Core/ArchSpec.h new file mode 100644 index 0000000..3bfa96b --- /dev/null +++ b/include/lldb/Core/ArchSpec.h @@ -0,0 +1,422 @@ +//===-- ArchSpec.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_ArchSpec_h_ +#define liblldb_ArchSpec_h_ + +#if defined(__cplusplus) + +#include "lldb/lldb-private.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" + +namespace lldb_private { + +struct CoreDefinition; + +//---------------------------------------------------------------------- +/// @class ArchSpec ArchSpec.h "lldb/Core/ArchSpec.h" +/// @brief An architecture specification class. +/// +/// A class designed to be created from a cpu type and subtype, a +/// string representation, or an llvm::Triple. Keeping all of the +/// conversions of strings to architecture enumeration values confined +/// to this class allows new architecture support to be added easily. +//---------------------------------------------------------------------- +class ArchSpec +{ +public: + enum Core + { + eCore_arm_generic, + eCore_arm_armv4, + eCore_arm_armv4t, + eCore_arm_armv5, + eCore_arm_armv5e, + eCore_arm_armv5t, + eCore_arm_armv6, + eCore_arm_armv7, + eCore_arm_armv7f, + eCore_arm_armv7s, + eCore_arm_armv7k, + eCore_arm_armv7m, + eCore_arm_armv7em, + eCore_arm_xscale, + eCore_thumb, + eCore_thumbv4t, + eCore_thumbv5, + eCore_thumbv5e, + eCore_thumbv6, + eCore_thumbv7, + eCore_thumbv7f, + eCore_thumbv7s, + eCore_thumbv7k, + eCore_thumbv7m, + eCore_thumbv7em, + + eCore_ppc_generic, + eCore_ppc_ppc601, + eCore_ppc_ppc602, + eCore_ppc_ppc603, + eCore_ppc_ppc603e, + eCore_ppc_ppc603ev, + eCore_ppc_ppc604, + eCore_ppc_ppc604e, + eCore_ppc_ppc620, + eCore_ppc_ppc750, + eCore_ppc_ppc7400, + eCore_ppc_ppc7450, + eCore_ppc_ppc970, + + eCore_ppc64_generic, + eCore_ppc64_ppc970_64, + + eCore_sparc_generic, + + eCore_sparc9_generic, + + eCore_x86_32_i386, + eCore_x86_32_i486, + eCore_x86_32_i486sx, + + eCore_x86_64_x86_64, + eCore_uknownMach32, + eCore_uknownMach64, + kNumCores, + + kCore_invalid, + // The following constants are used for wildcard matching only + kCore_any, + kCore_arm_any, + kCore_ppc_any, + kCore_ppc64_any, + kCore_x86_32_any, + + kCore_arm_first = eCore_arm_generic, + kCore_arm_last = eCore_arm_xscale, + + kCore_thumb_first = eCore_thumb, + kCore_thumb_last = eCore_thumbv7em, + + kCore_ppc_first = eCore_ppc_generic, + kCore_ppc_last = eCore_ppc_ppc970, + + kCore_ppc64_first = eCore_ppc64_generic, + kCore_ppc64_last = eCore_ppc64_ppc970_64, + + kCore_x86_32_first = eCore_x86_32_i386, + kCore_x86_32_last = eCore_x86_32_i486sx + }; + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Default constructor that initializes the object with invalid + /// cpu type and subtype values. + //------------------------------------------------------------------ + ArchSpec (); + + //------------------------------------------------------------------ + /// Constructor over triple. + /// + /// Constructs an ArchSpec with properties consistent with the given + /// Triple. + //------------------------------------------------------------------ + explicit + ArchSpec (const llvm::Triple &triple); + explicit + ArchSpec (const char *triple_cstr); + explicit + ArchSpec (const char *triple_cstr, Platform *platform); + //------------------------------------------------------------------ + /// Constructor over architecture name. + /// + /// Constructs an ArchSpec with properties consistent with the given + /// object type and architecture name. + //------------------------------------------------------------------ + explicit + ArchSpec (ArchitectureType arch_type, + uint32_t cpu_type, + uint32_t cpu_subtype); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~ArchSpec (); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// @param[in] rhs another ArchSpec object to copy. + /// + /// @return A const reference to this object. + //------------------------------------------------------------------ + const ArchSpec& + operator= (const ArchSpec& rhs); + + static size_t + AutoComplete (const char *name, + StringList &matches); + + //------------------------------------------------------------------ + /// Returns a static string representing the current architecture. + /// + /// @return A static string correcponding to the current + /// architecture. + //------------------------------------------------------------------ + const char * + GetArchitectureName () const; + + //------------------------------------------------------------------ + /// Clears the object state. + /// + /// Clears the object state back to a default invalid state. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Returns the size in bytes of an address of the current + /// architecture. + /// + /// @return The byte size of an address of the current architecture. + //------------------------------------------------------------------ + uint32_t + GetAddressByteSize () const; + + //------------------------------------------------------------------ + /// Returns a machine family for the current architecture. + /// + /// @return An LLVM arch type. + //------------------------------------------------------------------ + llvm::Triple::ArchType + GetMachine () const; + + //------------------------------------------------------------------ + /// Tests if this ArchSpec is valid. + /// + /// @return True if the current architecture is valid, false + /// otherwise. + //------------------------------------------------------------------ + bool + IsValid () const + { + return m_core >= eCore_arm_generic && m_core < kNumCores; + } + + bool + TripleVendorWasSpecified() const + { + return !m_triple.getVendorName().empty(); + } + + bool + TripleOSWasSpecified() const + { + return !m_triple.getOSName().empty(); + } + + //------------------------------------------------------------------ + /// Sets this ArchSpec according to the given architecture name. + /// + /// The architecture name can be one of the generic system default + /// values: + /// + /// @li \c LLDB_ARCH_DEFAULT - The arch the current system defaults + /// to when a program is launched without any extra + /// attributes or settings. + /// @li \c LLDB_ARCH_DEFAULT_32BIT - The default host architecture + /// for 32 bit (if any). + /// @li \c LLDB_ARCH_DEFAULT_64BIT - The default host architecture + /// for 64 bit (if any). + /// + /// Alternatively, if the object type of this ArchSpec has been + /// configured, a concrete architecture can be specified to set + /// the CPU type ("x86_64" for example). + /// + /// Finally, an encoded object and archetecture format is accepted. + /// The format contains an object type (like "macho" or "elf"), + /// followed by a platform dependent encoding of CPU type and + /// subtype. For example: + /// + /// "macho" : Specifies an object type of MachO. + /// "macho-16-6" : MachO specific encoding for ARMv6. + /// "elf-43 : ELF specific encoding for Sparc V9. + /// + /// @param[in] arch_name The name of an architecture. + /// + /// @return True if @p arch_name was successfully translated, false + /// otherwise. + //------------------------------------------------------------------ +// bool +// SetArchitecture (const llvm::StringRef& arch_name); +// +// bool +// SetArchitecture (const char *arch_name); + + //------------------------------------------------------------------ + /// Change the architecture object type and CPU type. + /// + /// @param[in] arch_type The object type of this ArchSpec. + /// + /// @param[in] cpu The required CPU type. + /// + /// @return True if the object and CPU type were sucessfully set. + //------------------------------------------------------------------ + bool + SetArchitecture (ArchitectureType arch_type, + uint32_t cpu, + uint32_t sub); + + //------------------------------------------------------------------ + /// Returns the byte order for the architecture specification. + /// + /// @return The endian enumeration for the current endianness of + /// the architecture specification + //------------------------------------------------------------------ + lldb::ByteOrder + GetByteOrder () const; + + //------------------------------------------------------------------ + /// Sets this ArchSpec's byte order. + /// + /// In the common case there is no need to call this method as the + /// byte order can almost always be determined by the architecture. + /// However, many CPU's are bi-endian (ARM, Alpha, PowerPC, etc) + /// and the default/assumed byte order may be incorrect. + //------------------------------------------------------------------ + void + SetByteOrder (lldb::ByteOrder byte_order) + { + m_byte_order = byte_order; + } + + uint32_t + GetMinimumOpcodeByteSize() const; + + uint32_t + GetMaximumOpcodeByteSize() const; + + Core + GetCore () const + { + return m_core; + } + + uint32_t + GetMachOCPUType () const; + + uint32_t + GetMachOCPUSubType () const; + + //------------------------------------------------------------------ + /// Architecture tripple accessor. + /// + /// @return A triple describing this ArchSpec. + //------------------------------------------------------------------ + llvm::Triple & + GetTriple () + { + return m_triple; + } + + //------------------------------------------------------------------ + /// Architecture tripple accessor. + /// + /// @return A triple describing this ArchSpec. + //------------------------------------------------------------------ + const llvm::Triple & + GetTriple () const + { + return m_triple; + } + + //------------------------------------------------------------------ + /// Architecture tripple setter. + /// + /// Configures this ArchSpec according to the given triple. If the + /// triple has unknown components in all of the vendor, OS, and + /// the optional environment field (i.e. "i386-unknown-unknown") + /// then default values are taken from the host. Architecture and + /// environment components are used to further resolve the CPU type + /// and subtype, endian characteristics, etc. + /// + /// @return A triple describing this ArchSpec. + //------------------------------------------------------------------ + bool + SetTriple (const llvm::Triple &triple); + + bool + SetTriple (const char *triple_cstr); + + bool + SetTriple (const char *triple_cstr, + Platform *platform); + + //------------------------------------------------------------------ + /// Returns the default endianness of the architecture. + /// + /// @return The endian enumeration for the default endianness of + /// the architecture. + //------------------------------------------------------------------ + lldb::ByteOrder + GetDefaultEndian () const; + + //------------------------------------------------------------------ + /// Compare an ArchSpec to another ArchSpec, requiring an exact cpu + /// type match between them. + /// e.g. armv7s is not an exact match with armv7 - this would return false + /// + /// @return true if the two ArchSpecs match. + //------------------------------------------------------------------ + bool + IsExactMatch (const ArchSpec& rhs) const; + + //------------------------------------------------------------------ + /// Compare an ArchSpec to another ArchSpec, requiring a compatible + /// cpu type match between them. + /// e.g. armv7s is compatible with armv7 - this method would return true + /// + /// @return true if the two ArchSpecs are compatible + //------------------------------------------------------------------ + bool + IsCompatibleMatch (const ArchSpec& rhs) const; + +protected: + bool + IsEqualTo (const ArchSpec& rhs, bool exact_match) const; + + llvm::Triple m_triple; + Core m_core; + lldb::ByteOrder m_byte_order; + + // Called when m_def or m_entry are changed. Fills in all remaining + // members with default values. + void + CoreUpdated (bool update_triple); +}; + +//------------------------------------------------------------------ +/// @fn bool operator< (const ArchSpec& lhs, const ArchSpec& rhs) +/// @brief Less than operator. +/// +/// Tests two ArchSpec objects to see if \a lhs is less than \a +/// rhs. +/// +/// @param[in] lhs The Left Hand Side ArchSpec object to compare. +/// @param[in] rhs The Left Hand Side ArchSpec object to compare. +/// +/// @return true if \a lhs is less than \a rhs +//------------------------------------------------------------------ +bool operator< (const ArchSpec& lhs, const ArchSpec& rhs); + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // #ifndef liblldb_ArchSpec_h_ diff --git a/include/lldb/Core/Baton.h b/include/lldb/Core/Baton.h new file mode 100644 index 0000000..627e720 --- /dev/null +++ b/include/lldb/Core/Baton.h @@ -0,0 +1,62 @@ +//===-- Baton.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_Baton_h_ +#define lldb_Baton_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Baton Baton.h "lldb/Core/Baton.h" +/// @brief A class designed to wrap callback batons so they can cleanup +/// any acquired resources +/// +/// This class is designed to be used by any objects that have a +/// callback function that takes a baton where the baton might need to +/// free/delete/close itself. +/// +/// The default behavior is to not free anything. Subclasses can +/// free any needed resources in their destructors. +//---------------------------------------------------------------------- +class Baton +{ +public: + explicit Baton(void *p) : + m_data (p) + { + } + + virtual + ~Baton() + { + // The default destructor for a baton does NOT attempt to clean up + // anything in m_baton + } + + virtual void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + + void *m_data; // Leave baton public for easy access + +private: + //------------------------------------------------------------------ + // For Baton only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (Baton); +}; + +} // namespace lldb_private + +#endif // lldb_Baton_h_ diff --git a/include/lldb/Core/Broadcaster.h b/include/lldb/Core/Broadcaster.h new file mode 100644 index 0000000..64b12ca --- /dev/null +++ b/include/lldb/Core/Broadcaster.h @@ -0,0 +1,475 @@ +//===-- Broadcaster.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_Broadcaster_h_ +#define liblldb_Broadcaster_h_ + +// C Includes +// C++ Includes +#include <map> +#include <string> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +//#include "lldb/Core/Flags.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Listener.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// lldb::BroadcastEventSpec +// +// This class is used to specify a kind of event to register for. The Debugger +// maintains a list of BroadcastEventSpec's and when it is made +//---------------------------------------------------------------------- +class BroadcastEventSpec +{ +public: + BroadcastEventSpec (const ConstString &broadcaster_class, uint32_t event_bits) : + m_broadcaster_class (broadcaster_class), + m_event_bits (event_bits) + { + } + + BroadcastEventSpec (const BroadcastEventSpec &rhs); + + ~BroadcastEventSpec() {} + + const ConstString &GetBroadcasterClass() const + { + return m_broadcaster_class; + } + + uint32_t GetEventBits () const + { + return m_event_bits; + } + + // Tell whether this BroadcastEventSpec is contained in in_spec. + // That is: + // (a) the two spec's share the same broadcaster class + // (b) the event bits of this spec are wholly contained in those of in_spec. + bool IsContainedIn (BroadcastEventSpec in_spec) const + { + if (m_broadcaster_class != in_spec.GetBroadcasterClass()) + return false; + uint32_t in_bits = in_spec.GetEventBits(); + if (in_bits == m_event_bits) + return true; + else + { + if ((m_event_bits & in_bits) != 0 + && (m_event_bits & ~in_bits) == 0) + return true; + } + return false; + } + + bool operator< (const BroadcastEventSpec &rhs) const; + const BroadcastEventSpec &operator= (const BroadcastEventSpec &rhs); + +private: + ConstString m_broadcaster_class; + uint32_t m_event_bits; +}; + +class BroadcasterManager +{ +public: + friend class Listener; + + BroadcasterManager (); + + ~BroadcasterManager () {} + + uint32_t + RegisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec); + + bool + UnregisterListenerForEvents (Listener &listener, BroadcastEventSpec event_spec); + + Listener * + GetListenerForEventSpec (BroadcastEventSpec event_spec) const; + + void + SignUpListenersForBroadcaster (Broadcaster &broadcaster); + + void + RemoveListener (Listener &Listener); + +protected: + void Clear(); + +private: + typedef std::pair<BroadcastEventSpec, Listener *> event_listener_key; + typedef std::map<BroadcastEventSpec, Listener *> collection; + typedef std::set<Listener *> listener_collection; + collection m_event_map; + listener_collection m_listeners; + + Mutex m_manager_mutex; + + // A couple of comparator classes for find_if: + + class BroadcasterClassMatches + { + public: + BroadcasterClassMatches (const ConstString &broadcaster_class) : + m_broadcaster_class (broadcaster_class) + { + } + + ~BroadcasterClassMatches () {} + + bool operator() (const event_listener_key input) const + { + return (input.first.GetBroadcasterClass() == m_broadcaster_class); + } + + private: + ConstString m_broadcaster_class; + }; + + class BroadcastEventSpecMatches + { + public: + BroadcastEventSpecMatches (BroadcastEventSpec broadcaster_spec) : + m_broadcaster_spec (broadcaster_spec) + { + } + + ~BroadcastEventSpecMatches () {} + + bool operator() (const event_listener_key input) const + { + return (input.first.IsContainedIn (m_broadcaster_spec)); + } + + private: + BroadcastEventSpec m_broadcaster_spec; + }; + + class ListenerMatchesAndSharedBits + { + public: + ListenerMatchesAndSharedBits (BroadcastEventSpec broadcaster_spec, + const Listener &listener) : + m_broadcaster_spec (broadcaster_spec), + m_listener (&listener) + { + } + + ~ListenerMatchesAndSharedBits () {} + + bool operator() (const event_listener_key input) const + { + return (input.first.GetBroadcasterClass() == m_broadcaster_spec.GetBroadcasterClass() + && (input.first.GetEventBits() & m_broadcaster_spec.GetEventBits()) != 0 + && input.second == m_listener); + } + + private: + BroadcastEventSpec m_broadcaster_spec; + const Listener *m_listener; + }; + + class ListenerMatches + { + public: + ListenerMatches (const Listener &in_listener) : + m_listener (&in_listener) + { + } + + ~ListenerMatches() {} + + bool operator () (const event_listener_key input) const + { + if (input.second == m_listener) + return true; + else + return false; + } + + private: + const Listener *m_listener; + + }; + +}; + +//---------------------------------------------------------------------- +/// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h" +/// @brief An event broadcasting class. +/// +/// The Broadcaster class is designed to be subclassed by objects that +/// wish to vend events in a multi-threaded environment. Broadcaster +/// objects can each vend 32 events. Each event is represented by a bit +/// in a 32 bit value and these bits can be set: +/// @see Broadcaster::SetEventBits(uint32_t) +/// or cleared: +/// @see Broadcaster::ResetEventBits(uint32_t) +/// When an event gets set the Broadcaster object will notify the +/// Listener object that is listening for the event (if there is one). +/// +/// Subclasses should provide broadcast bit definitions for any events +/// they vend, typically using an enumeration: +/// \code +/// class Foo : public Broadcaster +/// { +/// public: +/// //---------------------------------------------------------- +/// // Broadcaster event bits definitions. +/// //---------------------------------------------------------- +/// enum +/// { +/// eBroadcastBitStateChanged = (1 << 0), +/// eBroadcastBitInterrupt = (1 << 1), +/// eBroadcastBitSTDOUT = (1 << 2), +/// eBroadcastBitSTDERR = (1 << 3), +/// eBroadcastBitProfileData = (1 << 4) +/// }; +/// \endcode +//---------------------------------------------------------------------- +class Broadcaster +{ +public: + //------------------------------------------------------------------ + /// Construct with a broadcaster with a name. + /// + /// @param[in] name + /// A NULL terminated C string that contains the name of the + /// broadcaster object. + //------------------------------------------------------------------ + Broadcaster (BroadcasterManager *manager, const char *name); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class gets subclassed. + //------------------------------------------------------------------ + virtual + ~Broadcaster(); + + void + CheckInWithManager (); + + //------------------------------------------------------------------ + /// Broadcast an event which has no associated data. + /// + /// @param[in] event_type + /// The element from the enum defining this broadcaster's events + /// that is being broadcast. + /// + /// @param[in] event_data + /// User event data that will be owned by the lldb::Event that + /// is created internally. + /// + /// @param[in] unique + /// If true, then only add an event of this type if there isn't + /// one already in the queue. + /// + //------------------------------------------------------------------ + void + BroadcastEvent (lldb::EventSP &event_sp); + + void + BroadcastEventIfUnique (lldb::EventSP &event_sp); + + void + BroadcastEvent (uint32_t event_type, EventData *event_data = NULL); + + void + BroadcastEventIfUnique (uint32_t event_type, EventData *event_data = NULL); + + void + Clear(); + + virtual void + AddInitialEventsToListener (Listener *listener, uint32_t requested_events); + + //------------------------------------------------------------------ + /// Listen for any events specified by \a event_mask. + /// + /// Only one listener can listen to each event bit in a given + /// Broadcaster. Once a listener has acquired an event bit, no + /// other broadcaster will have access to it until it is + /// relinquished by the first listener that gets it. The actual + /// event bits that get acquired by \a listener may be different + /// from what is requested in \a event_mask, and to track this the + /// actual event bits that are acquired get returned. + /// + /// @param[in] listener + /// The Listener object that wants to monitor the events that + /// get broadcast by this object. + /// + /// @param[in] event_mask + /// A bit mask that indicates which events the listener is + /// asking to monitor. + /// + /// @return + /// The actual event bits that were acquired by \a listener. + //------------------------------------------------------------------ + uint32_t + AddListener (Listener* listener, uint32_t event_mask); + + //------------------------------------------------------------------ + /// Get the NULL terminated C string name of this Broadcaster + /// object. + /// + /// @return + /// The NULL terminated C string name of this Broadcaster. + //------------------------------------------------------------------ + const ConstString & + GetBroadcasterName (); + + + //------------------------------------------------------------------ + /// Get the event name(s) for one or more event bits. + /// + /// @param[in] event_mask + /// A bit mask that indicates which events to get names for. + /// + /// @return + /// The NULL terminated C string name of this Broadcaster. + //------------------------------------------------------------------ + bool + GetEventNames (Stream &s, const uint32_t event_mask, bool prefix_with_broadcaster_name) const; + + //------------------------------------------------------------------ + /// Set the name for an event bit. + /// + /// @param[in] event_mask + /// A bit mask that indicates which events the listener is + /// asking to monitor. + /// + /// @return + /// The NULL terminated C string name of this Broadcaster. + //------------------------------------------------------------------ + void + SetEventName (uint32_t event_mask, const char *name) + { + m_event_names[event_mask] = name; + } + + const char * + GetEventName (uint32_t event_mask) const + { + event_names_map::const_iterator pos = m_event_names.find (event_mask); + if (pos != m_event_names.end()) + return pos->second.c_str(); + return NULL; + } + + bool + EventTypeHasListeners (uint32_t event_type); + + //------------------------------------------------------------------ + /// Removes a Listener from this broadcasters list and frees the + /// event bits specified by \a event_mask that were previously + /// acquired by \a listener (assuming \a listener was listening to + /// this object) for other listener objects to use. + /// + /// @param[in] listener + /// A Listener object that previously called AddListener. + /// + /// @param[in] event_mask + /// The event bits \a listener wishes to relinquish. + /// + /// @return + /// \b True if the listener was listening to this broadcaster + /// and was removed, \b false otherwise. + /// + /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t) + //------------------------------------------------------------------ + bool + RemoveListener (Listener* listener, uint32_t event_mask = UINT32_MAX); + + //------------------------------------------------------------------ + /// Provides a simple mechanism to temporarily redirect events from + /// broadcaster. When you call this function passing in a listener and + /// event type mask, all events from the broadcaster matching the mask + /// will now go to the hijacking listener. + /// Only one hijack can occur at a time. If we need more than this we + /// will have to implement a Listener stack. + /// + /// @param[in] listener + /// A Listener object. You do not need to call StartListeningForEvents + /// for this broadcaster (that would fail anyway since the event bits + /// would most likely be taken by the listener(s) you are usurping. + /// + /// @param[in] event_mask + /// The event bits \a listener wishes to hijack. + /// + /// @return + /// \b True if the event mask could be hijacked, \b false otherwise. + /// + /// @see uint32_t Broadcaster::AddListener (Listener*, uint32_t) + //------------------------------------------------------------------ + bool + HijackBroadcaster (Listener *listener, uint32_t event_mask = UINT32_MAX); + + bool + IsHijackedForEvent (uint32_t event_mask) + { + if (m_hijacking_listeners.size() > 0) + return (event_mask & m_hijacking_masks.back()) != 0; + return false; + } + + //------------------------------------------------------------------ + /// Restore the state of the Broadcaster from a previous hijack attempt. + /// + //------------------------------------------------------------------ + void + RestoreBroadcaster (); + + // This needs to be filled in if you are going to register the broadcaster with the broadcaster + // manager and do broadcaster class matching. + // FIXME: Probably should make a ManagedBroadcaster subclass with all the bits needed to work + // with the BroadcasterManager, so that it is clearer how to add one. + virtual ConstString &GetBroadcasterClass() const; + + BroadcasterManager *GetManager(); + +protected: + + + void + PrivateBroadcastEvent (lldb::EventSP &event_sp, bool unique); + + //------------------------------------------------------------------ + // Classes that inherit from Broadcaster can see and modify these + //------------------------------------------------------------------ + typedef std::vector< std::pair<Listener*,uint32_t> > collection; + typedef std::map<uint32_t, std::string> event_names_map; + // Prefix the name of our member variables with "m_broadcaster_" + // since this is a class that gets subclassed. + const ConstString m_broadcaster_name; ///< The name of this broadcaster object. + event_names_map m_event_names; ///< Optionally define event names for readability and logging for each event bit + collection m_listeners; ///< A list of Listener / event_mask pairs that are listening to this broadcaster. + Mutex m_listeners_mutex; ///< A mutex that protects \a m_listeners. + std::vector<Listener *> m_hijacking_listeners; // A simple mechanism to intercept events from a broadcaster + std::vector<uint32_t> m_hijacking_masks; // At some point we may want to have a stack or Listener + // collections, but for now this is just for private hijacking. + BroadcasterManager *m_manager; + +private: + //------------------------------------------------------------------ + // For Broadcaster only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (Broadcaster); +}; + +} // namespace lldb_private + +#endif // liblldb_Broadcaster_h_ diff --git a/include/lldb/Core/ClangForward.h b/include/lldb/Core/ClangForward.h new file mode 100644 index 0000000..0b3f13a --- /dev/null +++ b/include/lldb/Core/ClangForward.h @@ -0,0 +1,136 @@ +//===-- ClangForward.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_ClangForward_h_ +#define liblldb_ClangForward_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes + +#if defined(__cplusplus) + +namespace clang +{ + namespace Builtin + { + class Context; + } + + class Action; + class ASTConsumer; + class ASTContext; + class ASTRecordLayout; + class AddrLabelExpr; + class AnalyzerOptions; + class BinaryOperator; + class ClassTemplateDecl; + class ClassTemplateSpecializationDecl; + class CodeGenOptions; + class CodeGenerator; + class CompilerInstance; + class CompoundStmt; + class CXXBaseSpecifier; + class CXXBoolLiteralExpr; + class CXXFunctionalCastExpr; + class CXXMethodDecl; + class CXXNamedCastExpr; + class CXXRecordDecl; + class CXXThisExpr; + class CharacterLiteral; + class CompoundAssignOperator; + class Decl; + class DeclarationName; + class DeclaratorDecl; + class DeclContext; + class DeclRefExpr; + class DeclStmt; + class DependencyOutputOptions; + class Diagnostic; + class DiagnosticConsumer; + class DiagnosticsEngine; + class DiagnosticOptions; + class EnumDecl; + class Expr; + class ExternalASTSource; + class ExtVectorElementExpr; + class FieldDecl; + class FileManager; + class FileSystemOptions; + class FloatingLiteral; + class FrontendOptions; + class FunctionDecl; + class FunctionTemplateDecl; + class FunctionTemplateSpecializationInfo; + class GotoStmt; + class HeaderSearchOptions; + class IdentifierTable; + class IntegerLiteral; + class LabelStmt; + class LangOptions; + class MemberExpr; + class NamedDecl; + class NamespaceDecl; + class NonTypeTemplateParmDecl; + class ObjCEncodeExpr; + class ObjCImplicitSetterGetterRefExpr; + class ObjCInterfaceDecl; + class ObjCIvarDecl; + class ObjCIvarRefExpr; + class ObjCMessageExpr; + class ObjCMethodDecl; + class ObjCPropertyRefExpr; + class ObjCProtocolDecl; + class ObjCProtocolExpr; + class ObjCSelectorExpr; + class ObjCSuperExpr; + class ParenExpr; + class ParmVarDecl; + class PredefinedExpr; + class PreprocessorOptions; + class PreprocessorOutputOptions; + class QualType; + class QualifiedNameType; + class RecordDecl; + class SelectorTable; + class SizeOfAlignOfExpr; + class SourceLocation; + class SourceManager; + class Stmt; + class StmtIteratorBase; + class StringLiteral; + class TagDecl; + class TargetInfo; + class TargetOptions; + class TemplateArgument; + class TemplateDecl; + class TemplateParameterList; + class TemplateTemplateParmDecl; + class TemplateTypeParmDecl; + class TextDiagnosticBuffer; + class TranslationUnitDecl; + class Type; + class TypeDecl; + class TypedefDecl; + class TypesCompatibleExpr; + class UnaryOperator; + class ValueDecl; + class VarDecl; + struct PrintingPolicy; +} + +namespace llvm +{ + class LLVMContext; + class ExecutionEngine; +} + +#endif // #if defined(__cplusplus) +#endif // liblldb_ClangForward_h_ diff --git a/include/lldb/Core/Communication.h b/include/lldb/Core/Communication.h new file mode 100644 index 0000000..98d4dfd --- /dev/null +++ b/include/lldb/Core/Communication.h @@ -0,0 +1,413 @@ +//===-- Communication.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_Communication_h_ +#define liblldb_Communication_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Error.h" +#include "lldb/Host/Mutex.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Communication Communication.h "lldb/Core/Communication.h" +/// @brief An abstract communications class. +/// +/// Communication is an class that handles data communication +/// between two data sources. It uses a Connection class to do the +/// real communication. This approach has a couple of advantages: it +/// allows a single instance of this class to be used even though its +/// connection can change. Connections could negotiate for different +/// connections based on abilities like starting with Bluetooth and +/// negotiating up to WiFi if available. It also allows this class to be +/// subclassed by any interfaces that don't want to give bytes but want +/// to validate and give out packets. This can be done by overriding: +/// +/// AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast); +/// +/// Communication inherits from Broadcaster which means it can be +/// used in conjunction with Listener to wait for multiple broadcaster +/// objects and multiple events from each of those objects. +/// Communication defines a set of pre-defined event bits (see +/// enumerations definitions that start with "eBroadcastBit" below). +/// +/// There are two modes in which communications can occur: +/// @li single-threaded +/// @li multi-threaded +/// +/// In single-threaded mode, all reads and writes happen synchronously +/// on the calling thread. +/// +/// In multi-threaded mode, a read thread is spawned that continually +/// reads data and caches any received bytes. To start the read thread +/// clients call: +/// +/// bool Communication::StartReadThread (Error *); +/// +/// If true is returned a read thead has been spawned that will +/// continually execute a call to the pure virtual DoRead function: +/// +/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t); +/// +/// When bytes are received the data gets cached in \a m_bytes and this +/// class will broadcast a \b eBroadcastBitReadThreadGotBytes event. +/// Clients that want packet based communication should override +/// AppendBytesToCache. The subclasses can choose to call the +/// built in AppendBytesToCache with the \a broadcast parameter set to +/// false. This will cause the \b eBroadcastBitReadThreadGotBytes event +/// not get broadcast, and then the subclass can post a \b +/// eBroadcastBitPacketAvailable event when a full packet of data has +/// been received. +/// +/// If the connection is disconnected a \b eBroadcastBitDisconnected +/// event gets broadcast. If the read thread exits a \b +/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients +/// can also post a \b eBroadcastBitReadThreadShouldExit event to this +/// object which will cause the read thread to exit. +//---------------------------------------------------------------------- +class Communication : public Broadcaster +{ +public: + enum { + eBroadcastBitDisconnected = (1 << 0), ///< Sent when the communications connection is lost. + eBroadcastBitReadThreadGotBytes = (1 << 1), ///< Sent by the read thread when bytes become available. + eBroadcastBitReadThreadDidExit = (1 << 2), ///< Sent by the read thread when it exits to inform clients. + eBroadcastBitReadThreadShouldExit = (1 << 3), ///< Sent by clients that need to cancel the read thread. + eBroadcastBitPacketAvailable = (1 << 4), ///< Sent when data received makes a complete packet. + kLoUserBroadcastBit = (1 << 16),///< Subclasses can used bits 31:16 for any needed events. + kHiUserBroadcastBit = (1 << 31), + eAllEventBits = 0xffffffff + }; + + typedef void (*ReadThreadBytesReceived) (void *baton, const void *src, size_t src_len); + + + //------------------------------------------------------------------ + /// Construct the Communication object with the specified name for + /// the Broadcaster that this object inherits from. + /// + /// @param[in] broadcaster_name + /// The name of the broadcaster object. This name should be as + /// complete as possible to uniquely identify this object. The + /// broadcaster name can be updated after the connect function + /// is called. + //------------------------------------------------------------------ + Communication(const char * broadcaster_name); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class gets subclassed. + //------------------------------------------------------------------ + virtual + ~Communication(); + + void + Clear (); + + //------------------------------------------------------------------ + /// Connect using the current connection by passing \a url to its + /// connect function. + /// string. + /// + /// @param[in] url + /// A string that contains all information needed by the + /// subclass to connect to another client. + /// + /// @return + /// \b True if the connect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// @see Error& Communication::GetError (); + /// @see bool Connection::Connect (const char *url); + //------------------------------------------------------------------ + lldb::ConnectionStatus + Connect (const char *url, Error *error_ptr); + + //------------------------------------------------------------------ + /// Disconnect the communications connection if one is currently + /// connected. + /// + /// @return + /// \b True if the disconnect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// @see Error& Communication::GetError (); + /// @see bool Connection::Disconnect (); + //------------------------------------------------------------------ + lldb::ConnectionStatus + Disconnect (Error *error_ptr = NULL); + + //------------------------------------------------------------------ + /// Check if the connection is valid. + /// + /// @return + /// \b True if this object is currently connected, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + IsConnected () const; + + bool + HasConnection () const; + + lldb_private::Connection * + GetConnection () + { + return m_connection_sp.get(); + } + //------------------------------------------------------------------ + /// Read bytes from the current connection. + /// + /// If no read thread is running, this function call the + /// connection's Connection::Read(...) function to get any available. + /// + /// If a read thread has been started, this function will check for + /// any cached bytes that have already been read and return any + /// currently available bytes. If no bytes are cached, it will wait + /// for the bytes to become available by listening for the \a + /// eBroadcastBitReadThreadGotBytes event. If this function consumes + /// all of the bytes in the cache, it will reset the + /// \a eBroadcastBitReadThreadGotBytes event bit. + /// + /// @param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// @param[in] dst_len + /// The number of bytes to attempt to read, and also the max + /// number of bytes that can be placed into \a dst. + /// + /// @param[in] timeout_usec + /// A timeout value in micro-seconds. + /// + /// @return + /// The number of bytes actually read. + /// + /// @see size_t Connection::Read (void *, size_t); + //------------------------------------------------------------------ + size_t + Read (void *dst, + size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + Error *error_ptr); + + //------------------------------------------------------------------ + /// The actual write function that attempts to write to the + /// communications protocol. + /// + /// Subclasses must override this function. + /// + /// @param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// @param[in] src_len + /// The number of bytes to attempt to write, and also the + /// number of bytes are currently available in \a src. + /// + /// @return + /// The number of bytes actually Written. + //------------------------------------------------------------------ + size_t + Write (const void *src, + size_t src_len, + lldb::ConnectionStatus &status, + Error *error_ptr); + + //------------------------------------------------------------------ + /// Sets the connection that it to be used by this class. + /// + /// By making a communication class that uses different connections + /// it allows a single communication interface to negotiate and + /// change its connection without any interruption to the client. + /// It also allows the Communication class to be subclassed for + /// packet based communication. + /// + /// @param[in] connection + /// A connection that this class will own and destroy. + /// + /// @see + /// class Connection + //------------------------------------------------------------------ + void + SetConnection (Connection *connection); + + //------------------------------------------------------------------ + /// Starts a read thread whose sole purpose it to read bytes from + /// the current connection. This function will call connection's + /// read function: + /// + /// size_t Connection::Read (void *, size_t); + /// + /// When bytes are read and cached, this function will call: + /// + /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast); + /// + /// Subclasses should override this function if they wish to override + /// the default action of caching the bytes and broadcasting a \b + /// eBroadcastBitReadThreadGotBytes event. + /// + /// @return + /// \b True if the read thread was successfully started, \b + /// false otherwise. + /// + /// @see size_t Connection::Read (void *, size_t); + /// @see void Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast); + //------------------------------------------------------------------ + virtual bool + StartReadThread (Error *error_ptr = NULL); + + //------------------------------------------------------------------ + /// Stops the read thread by cancelling it. + /// + /// @return + /// \b True if the read thread was successfully canceled, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + StopReadThread (Error *error_ptr = NULL); + + //------------------------------------------------------------------ + /// Checks if there is a currently running read thread. + /// + /// @return + /// \b True if the read thread is running, \b false otherwise. + //------------------------------------------------------------------ + bool + ReadThreadIsRunning (); + + //------------------------------------------------------------------ + /// The static read thread function. This function will call + /// the "DoRead" function continuously and wait for data to become + /// avaialble. When data is received it will append the available + /// data to the internal cache and broadcast a + /// \b eBroadcastBitReadThreadGotBytes event. + /// + /// @param[in] comm_ptr + /// A pointer to an instance of this class. + /// + /// @return + /// \b NULL. + /// + /// @see void Communication::ReadThreadGotBytes (const uint8_t *, size_t); + //------------------------------------------------------------------ + static lldb::thread_result_t + ReadThread (lldb::thread_arg_t comm_ptr); + + void + SetReadThreadBytesReceivedCallback (ReadThreadBytesReceived callback, + void *callback_baton); + + static const char * + ConnectionStatusAsCString (lldb::ConnectionStatus status); + + bool + GetCloseOnEOF () const + { + return m_close_on_eof; + } + + void + SetCloseOnEOF (bool b) + { + m_close_on_eof = b; + } + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + +private: + //------------------------------------------------------------------ + // For Communication only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (Communication); + + +protected: + lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use by this communications class. + lldb::thread_t m_read_thread; ///< The read thread handle in case we need to cancel the thread. + bool m_read_thread_enabled; + std::string m_bytes; ///< A buffer to cache bytes read in the ReadThread function. + Mutex m_bytes_mutex; ///< A mutex to protect multi-threaded access to the cached bytes. + Mutex m_write_mutex; ///< Don't let multiple threads write at the same time... + ReadThreadBytesReceived m_callback; + void *m_callback_baton; + bool m_close_on_eof; + + size_t + ReadFromConnection (void *dst, + size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + Error *error_ptr); + //------------------------------------------------------------------ + /// Append new bytes that get read from the read thread into the + /// internal object byte cache. This will cause a \b + /// eBroadcastBitReadThreadGotBytes event to be broadcast if \a + /// broadcast is true. + /// + /// Subclasses can override this function in order to inspect the + /// received data and check if a packet is available. + /// + /// Subclasses can also still call this function from the + /// overridden method to allow the caching to correctly happen and + /// suppress the broadcasting of the \a eBroadcastBitReadThreadGotBytes + /// event by setting \a broadcast to false. + /// + /// @param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// @param[in] src_len + /// The number of bytes to append to the cache. + //------------------------------------------------------------------ + virtual void + AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast, lldb::ConnectionStatus status); + + //------------------------------------------------------------------ + /// Get any available bytes from our data cache. If this call + /// empties the data cache, the \b eBroadcastBitReadThreadGotBytes event + /// will be reset to signify no more bytes are available. + /// + /// @param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// @param[in] dst_len + /// The number of bytes to attempt to read from the cache, + /// and also the max number of bytes that can be placed into + /// \a dst. + /// + /// @return + /// The number of bytes extracted from the data cache. + //------------------------------------------------------------------ + size_t + GetCachedBytes (void *dst, size_t dst_len); +}; + +} // namespace lldb_private + +#endif // liblldb_Communication_h_ diff --git a/include/lldb/Core/Connection.h b/include/lldb/Core/Connection.h new file mode 100644 index 0000000..dde3c4b --- /dev/null +++ b/include/lldb/Core/Connection.h @@ -0,0 +1,162 @@ +//===-- Connection.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_Connection_h_ +#define liblldb_Connection_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Connection Connection.h "lldb/Core/Connection.h" +/// @brief A communication connection class. +/// +/// A class that implements that actual communication functions for +/// connecting/disconnecting, reading/writing, and waiting for bytes +/// to become available from a two way communication connection. +/// +/// This class is designed to only do very simple communication +/// functions. Instances can be instantiated and given to a +/// Communication class to perform communications where clients can +/// listen for broadcasts, and perform other higher level communications. +//---------------------------------------------------------------------- +class Connection +{ +public: + //------------------------------------------------------------------ + /// Default constructor + //------------------------------------------------------------------ + Connection (); + + //------------------------------------------------------------------ + /// Virtual destructor since this class gets subclassed and handed + /// to a Communication object. + //------------------------------------------------------------------ + virtual + ~Connection (); + + //------------------------------------------------------------------ + /// Connect using the connect string \a url. + /// + /// @param[in] url + /// A string that contains all information needed by the + /// subclass to connect to another client. + /// + /// @param[out] error_ptr + /// A pointer to an error object that should be given an + /// approriate error value if this method returns false. This + /// value can be NULL if the error value should be ignored. + /// + /// @return + /// \b True if the connect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// @see Error& Communication::GetError (); + //------------------------------------------------------------------ + virtual lldb::ConnectionStatus + Connect (const char *url, Error *error_ptr) = 0; + + //------------------------------------------------------------------ + /// Disconnect the communications connection if one is currently + /// connected. + /// + /// @param[out] error_ptr + /// A pointer to an error object that should be given an + /// approriate error value if this method returns false. This + /// value can be NULL if the error value should be ignored. + /// + /// @return + /// \b True if the disconnect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// @see Error& Communication::GetError (); + //------------------------------------------------------------------ + virtual lldb::ConnectionStatus + Disconnect (Error *error_ptr) = 0; + + //------------------------------------------------------------------ + /// Check if the connection is valid. + /// + /// @return + /// \b True if this object is currently connected, \b false + /// otherwise. + //------------------------------------------------------------------ + virtual bool + IsConnected () const = 0; + + //------------------------------------------------------------------ + /// The read function that attempts to read from the connection. + /// + /// @param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// @param[in] dst_len + /// The number of bytes to attempt to read, and also the max + /// number of bytes that can be placed into \a dst. + /// + /// @param[out] error_ptr + /// A pointer to an error object that should be given an + /// approriate error value if this method returns zero. This + /// value can be NULL if the error value should be ignored. + /// + /// @return + /// The number of bytes actually read. + /// + /// @see size_t Communication::Read (void *, size_t, uint32_t); + //------------------------------------------------------------------ + virtual size_t + Read (void *dst, + size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + Error *error_ptr) = 0; + + //------------------------------------------------------------------ + /// The actual write function that attempts to write to the + /// communications protocol. + /// + /// Subclasses must override this function. + /// + /// @param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// @param[in] src_len + /// The number of bytes to attempt to write, and also the + /// number of bytes are currently available in \a src. + /// + /// @param[out] error_ptr + /// A pointer to an error object that should be given an + /// approriate error value if this method returns zero. This + /// value can be NULL if the error value should be ignored. + /// + /// @return + /// The number of bytes actually Written. + //------------------------------------------------------------------ + virtual size_t + Write (const void *buffer, size_t length, lldb::ConnectionStatus &status, Error *error_ptr) = 0; + +private: + //------------------------------------------------------------------ + // For Connection only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (Connection); +}; + +} // namespace lldb_private + +#endif // liblldb_Connection_h_ diff --git a/include/lldb/Core/ConnectionFileDescriptor.h b/include/lldb/Core/ConnectionFileDescriptor.h new file mode 100644 index 0000000..fe704d4 --- /dev/null +++ b/include/lldb/Core/ConnectionFileDescriptor.h @@ -0,0 +1,139 @@ +//===-- ConnectionFileDescriptor.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_ConnectionFileDescriptor_h_ +#define liblldb_ConnectionFileDescriptor_h_ + +// C Includes +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Connection.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Host/Predicate.h" +#include "lldb/Host/SocketAddress.h" + +namespace lldb_private { + +class ConnectionFileDescriptor : + public Connection +{ +public: + + ConnectionFileDescriptor (); + + ConnectionFileDescriptor (int fd, bool owns_fd); + + virtual + ~ConnectionFileDescriptor (); + + virtual bool + IsConnected () const; + + virtual lldb::ConnectionStatus + Connect (const char *s, Error *error_ptr); + + virtual lldb::ConnectionStatus + Disconnect (Error *error_ptr); + + virtual size_t + Read (void *dst, + size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + Error *error_ptr); + + virtual size_t + Write (const void *src, + size_t src_len, + lldb::ConnectionStatus &status, + Error *error_ptr); + + // If the read file descriptor is a socket, then return + // the port number that is being used by the socket. + in_port_t + GetReadPort () const; + + // If the write file descriptor is a socket, then return + // the port number that is being used by the socket. + in_port_t + GetWritePort () const; + +protected: + + void + OpenCommandPipe (); + + void + CloseCommandPipe (); + + lldb::ConnectionStatus + BytesAvailable (uint32_t timeout_usec, Error *error_ptr); + + lldb::ConnectionStatus + SocketListen (uint16_t listen_port_num, Error *error_ptr); + + lldb::ConnectionStatus + ConnectTCP (const char *host_and_port, Error *error_ptr); + + lldb::ConnectionStatus + ConnectUDP (const char *args, Error *error_ptr); + + lldb::ConnectionStatus + NamedSocketAccept (const char *socket_name, Error *error_ptr); + + lldb::ConnectionStatus + NamedSocketConnect (const char *socket_name, Error *error_ptr); + + lldb::ConnectionStatus + Close (int& fd, Error *error); + + typedef enum + { + eFDTypeFile, // Other FD requireing read/write + eFDTypeSocket, // Socket requiring send/recv + eFDTypeSocketUDP // Unconnected UDP socket requiring sendto/recvfrom + } FDType; + + int m_fd_send; + int m_fd_recv; + FDType m_fd_send_type; + FDType m_fd_recv_type; + SocketAddress m_udp_send_sockaddr; + bool m_should_close_fd; // True if this class should close the file descriptor when it goes away. + uint32_t m_socket_timeout_usec; + int m_pipe_read; // A pipe that we select on the reading end of along with + int m_pipe_write; // m_fd_recv so we can force ourselves out of the select. + Mutex m_mutex; + bool m_shutting_down; // This marks that we are shutting down so if we get woken up from BytesAvailable + // to disconnect, we won't try to read again. + + static in_port_t + GetSocketPort (int fd); + + static int + GetSocketOption(int fd, int level, int option_name, int &option_value); + + static int + SetSocketOption(int fd, int level, int option_name, int option_value); + + bool + SetSocketReceiveTimeout (uint32_t timeout_usec); + +private: + DISALLOW_COPY_AND_ASSIGN (ConnectionFileDescriptor); +}; + +} // namespace lldb_private + +#endif // liblldb_ConnectionFileDescriptor_h_ diff --git a/include/lldb/Core/ConnectionMachPort.h b/include/lldb/Core/ConnectionMachPort.h new file mode 100644 index 0000000..5613e7e --- /dev/null +++ b/include/lldb/Core/ConnectionMachPort.h @@ -0,0 +1,92 @@ +//===-- ConnectionMachPort.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#if defined(__APPLE__) + +#ifndef liblldb_ConnectionMachPort_h_ +#define liblldb_ConnectionMachPort_h_ + +// C Includes +#include <mach/mach.h> + +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Connection.h" + +class ConnectionMachPort : + public lldb_private::Connection +{ +public: + ConnectionMachPort (); + + virtual + ~ConnectionMachPort (); + + virtual bool + IsConnected () const; + + virtual lldb::ConnectionStatus + BytesAvailable (uint32_t timeout_usec, lldb_private::Error *error_ptr); + + virtual lldb::ConnectionStatus + Connect (const char *s, lldb_private::Error *error_ptr); + + virtual lldb::ConnectionStatus + Disconnect (lldb_private::Error *error_ptr); + + virtual size_t + Read (void *dst, + size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + lldb_private::Error *error_ptr); + + virtual size_t + Write (const void *src, + size_t src_len, + lldb::ConnectionStatus &status, + lldb_private::Error *error_ptr); + + lldb::ConnectionStatus + BootstrapCheckIn (const char *port_name, + lldb_private::Error *error_ptr); + + lldb::ConnectionStatus + BootstrapLookup (const char *port_name, + lldb_private::Error *error_ptr); + + struct PayloadType + { + uint32_t command; + uint32_t data_length; + uint8_t data[32]; + }; + + kern_return_t + Send (const PayloadType &payload); + + kern_return_t + Receive (PayloadType &payload); + + +protected: + mach_port_t m_task; + mach_port_t m_port; + +private: + + + DISALLOW_COPY_AND_ASSIGN (ConnectionMachPort); +}; + +#endif // liblldb_ConnectionMachPort_h_ + +#endif // #if defined(__APPLE__) diff --git a/include/lldb/Core/ConnectionSharedMemory.h b/include/lldb/Core/ConnectionSharedMemory.h new file mode 100644 index 0000000..0f9cdcb --- /dev/null +++ b/include/lldb/Core/ConnectionSharedMemory.h @@ -0,0 +1,70 @@ +//===-- ConnectionSharedMemory.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_ConnectionSharedMemory_h_ +#define liblldb_ConnectionSharedMemory_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Connection.h" +#include "lldb/Core/DataBufferMemoryMap.h" + +namespace lldb_private { + +class ConnectionSharedMemory : + public Connection +{ +public: + + ConnectionSharedMemory (); + + virtual + ~ConnectionSharedMemory (); + + virtual bool + IsConnected () const; + + virtual lldb::ConnectionStatus + BytesAvailable (uint32_t timeout_usec, Error *error_ptr); + + virtual lldb::ConnectionStatus + Connect (const char *s, Error *error_ptr); + + virtual lldb::ConnectionStatus + Disconnect (Error *error_ptr); + + virtual size_t + Read (void *dst, + size_t dst_len, + uint32_t timeout_usec, + lldb::ConnectionStatus &status, + Error *error_ptr); + + virtual size_t + Write (const void *src, size_t src_len, lldb::ConnectionStatus &status, Error *error_ptr); + + lldb::ConnectionStatus + Open (bool create, const char *name, size_t size, Error *error_ptr); + +protected: + + std::string m_name; + int m_fd; // One buffer that contains all we need + DataBufferMemoryMap m_mmap; +private: + DISALLOW_COPY_AND_ASSIGN (ConnectionSharedMemory); +}; + +} // namespace lldb_private + +#endif // liblldb_ConnectionSharedMemory_h_ diff --git a/include/lldb/Core/ConstString.h b/include/lldb/Core/ConstString.h new file mode 100644 index 0000000..e692d3b --- /dev/null +++ b/include/lldb/Core/ConstString.h @@ -0,0 +1,507 @@ +//===-- ConstString.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_ConstString_h_ +#define liblldb_ConstString_h_ +#if defined(__cplusplus) + +#include <assert.h> + +#include "lldb/lldb-private.h" +#include "llvm/ADT/StringRef.h" + + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ConstString ConstString.h "lldb/Core/ConstString.h" +/// @brief A uniqued constant string class. +/// +/// Provides an efficient way to store strings as uniqued strings. After +/// the strings are uniqued, finding strings that are equal to one +/// another is very fast as just the pointers need to be compared. It +/// also allows for many common strings from many different sources to +/// be shared to keep the memory footprint low. +/// +/// No reference counting is done on strings that are added to the +/// string pool, once strings are added they are in the string pool for +/// the life of the program. +//---------------------------------------------------------------------- +class ConstString +{ +public: + //------------------------------------------------------------------ + /// Default constructor + /// + /// Initializes the string to an empty string. + //------------------------------------------------------------------ + ConstString (): + m_string (NULL) + { + } + + + //------------------------------------------------------------------ + /// Copy constructor + /// + /// Copies the string value in \a rhs into this object. + /// + /// @param[in] rhs + /// Another string object to copy. + //------------------------------------------------------------------ + ConstString (const ConstString& rhs) : + m_string (rhs.m_string) + { + } + + explicit ConstString (const llvm::StringRef &s); + + //------------------------------------------------------------------ + /// Construct with C String value + /// + /// Constructs this object with a C string by looking to see if the + /// C string already exists in the global string pool. If it doesn't + /// exist, it is added to the string pool. + /// + /// @param[in] cstr + /// A NULL terminated C string to add to the string pool. + //------------------------------------------------------------------ + explicit ConstString (const char *cstr); + + //------------------------------------------------------------------ + /// Construct with C String value with max length + /// + /// Constructs this object with a C string with a length. If + /// \a max_cstr_len is greater than the actual length of the string, + /// the string length will be truncated. This allows substrings to + /// be created without the need to NULL terminate the string as it + /// is passed into this function. + /// + /// @param[in] cstr + /// A pointer to the first character in the C string. The C + /// string can be NULL terminated in a buffer that contains + /// more characters than the length of the stirng, or the + /// string can be part of another string and a new substring + /// can be created. + /// + /// @param[in] max_cstr_len + /// The max length of \a cstr. If the string length of \a cstr + /// is less than \a max_cstr_len, then the string will be + /// truncated. If the string length of \a cstr is greater than + /// \a max_cstr_len, then only max_cstr_len bytes will be used + /// from \a cstr. + //------------------------------------------------------------------ + explicit ConstString (const char *cstr, size_t max_cstr_len); + + //------------------------------------------------------------------ + /// Destructor + /// + /// Since constant string values are currently not reference counted, + /// there isn't much to do here. + //------------------------------------------------------------------ + ~ConstString () + { + } + + + //---------------------------------------------------------------------- + /// C string equality binary predicate function object for ConstString + /// objects. + //---------------------------------------------------------------------- + struct StringIsEqual + { + //-------------------------------------------------------------- + /// C equality test. + /// + /// Two C strings are equal when they are contained in ConstString + /// objects when their pointer values are equal to each other. + /// + /// @return + /// Returns \b true if the C string in \a lhs is equal to + /// the C string value in \a rhs, \b false otherwise. + //-------------------------------------------------------------- + bool operator()(const char* lhs, const char* rhs) const + { + return lhs == rhs; + } + }; + + //------------------------------------------------------------------ + /// Convert to bool operator. + /// + /// This allows code to check a ConstString object to see if it + /// contains a valid string using code such as: + /// + /// @code + /// ConstString str(...); + /// if (str) + /// { ... + /// @endcode + /// + /// @return + /// /b True this object contains a valid non-empty C string, \b + /// false otherwise. + //------------------------------------------------------------------ + operator bool() const + { + return m_string && m_string[0]; + } + + //------------------------------------------------------------------ + /// Assignment operator + /// + /// Assigns the string in this object with the value from \a rhs. + /// + /// @param[in] rhs + /// Another string object to copy into this object. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const ConstString& + operator = (const ConstString& rhs) + { + m_string = rhs.m_string; + return *this; + } + + //------------------------------------------------------------------ + /// Equal to operator + /// + /// Returns true if this string is equal to the string in \a rhs. + /// This operation is very fast as it results in a pointer + /// comparison since all strings are in a uniqued in a global string + /// pool. + /// + /// @param[in] rhs + /// Another string object to compare this object to. + /// + /// @return + /// @li \b true if this object is equal to \a rhs. + /// @li \b false if this object is not equal to \a rhs. + //------------------------------------------------------------------ + bool + operator == (const ConstString& rhs) const + { + // We can do a pointer compare to compare these strings since they + // must come from the same pool in order to be equal. + return m_string == rhs.m_string; + } + + //------------------------------------------------------------------ + /// Not equal to operator + /// + /// Returns true if this string is not equal to the string in \a rhs. + /// This operation is very fast as it results in a pointer + /// comparison since all strings are in a uniqued in a global string + /// pool. + /// + /// @param[in] rhs + /// Another string object to compare this object to. + /// + /// @return + /// @li \b true if this object is not equal to \a rhs. + /// @li \b false if this object is equal to \a rhs. + //------------------------------------------------------------------ + bool + operator != (const ConstString& rhs) const + { + return m_string != rhs.m_string; + } + + bool + operator < (const ConstString& rhs) const; + + //------------------------------------------------------------------ + /// Get the string value as a C string. + /// + /// Get the value of the contained string as a NULL terminated C + /// string value. + /// + /// If \a value_if_empty is NULL, then NULL will be returned. + /// + /// @return + /// Returns \a value_if_empty if the string is empty, otherwise + /// the C string value contained in this object. + //------------------------------------------------------------------ + const char * + AsCString(const char *value_if_empty = NULL) const + { + if (m_string == NULL) + return value_if_empty; + return m_string; + } + + //------------------------------------------------------------------ + /// Get the string value as a llvm::StringRef + /// + /// @return + /// Returns a new llvm::StringRef object filled in with the + /// needed data. + //------------------------------------------------------------------ + llvm::StringRef + GetStringRef () const + { + return llvm::StringRef (m_string, GetLength()); + } + + //------------------------------------------------------------------ + /// Get the string value as a C string. + /// + /// Get the value of the contained string as a NULL terminated C + /// string value. Similar to the ConstString::AsCString() function, + /// yet this function will always return NULL if the string is not + /// valid. So this function is a direct accessor to the string + /// pointer value. + /// + /// @return + /// Returns NULL the string is invalid, otherwise the C string + /// value contained in this object. + //------------------------------------------------------------------ + const char * + GetCString () const + { + return m_string; + } + + + //------------------------------------------------------------------ + /// Get the length in bytes of string value. + /// + /// The string pool stores the length of the string, so we can avoid + /// calling strlen() on the pointer value with this function. + /// + /// @return + /// Returns the number of bytes that this string occupies in + /// memory, not including the NULL termination byte. + //------------------------------------------------------------------ + size_t + GetLength () const; + + //------------------------------------------------------------------ + /// Clear this object's state. + /// + /// Clear any contained string and reset the value to the an empty + /// string value. + //------------------------------------------------------------------ + void + Clear () + { + m_string = NULL; + } + + //------------------------------------------------------------------ + /// Compare two string objects. + /// + /// Compares the C string values contained in \a lhs and \a rhs and + /// returns an integer result. + /// + /// NOTE: only call this function when you want a true string + /// comparision. If you want string equality use the, use the == + /// operator as it is much more efficient. Also if you want string + /// inequality, use the != operator for the same reasons. + /// + /// @param[in] lhs + /// The Left Hand Side const ConstString object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const ConstString object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + Compare (const ConstString& lhs, const ConstString& rhs); + + //------------------------------------------------------------------ + /// Dump the object description to a stream. + /// + /// Dump the string value to the stream \a s. If the contained string + /// is empty, print \a value_if_empty to the stream instead. If + /// \a value_if_empty is NULL, then nothing will be dumped to the + /// stream. + /// + /// @param[in] s + /// The stream that will be used to dump the object description. + /// + /// @param[in] value_if_empty + /// The value to dump if the string is empty. If NULL, nothing + /// will be output to the stream. + //------------------------------------------------------------------ + void + Dump (Stream *s, const char *value_if_empty = NULL) const; + + //------------------------------------------------------------------ + /// Dump the object debug description to a stream. + /// + /// @param[in] s + /// The stream that will be used to dump the object description. + //------------------------------------------------------------------ + void + DumpDebug (Stream *s) const; + + //------------------------------------------------------------------ + /// Test for empty string. + /// + /// @return + /// @li \b true if the contained string is empty. + /// @li \b false if the contained string is not empty. + //------------------------------------------------------------------ + bool + IsEmpty () const + { + return m_string == NULL || m_string[0] == '\0'; + } + + //------------------------------------------------------------------ + /// Set the C string value. + /// + /// Set the string value in the object by uniquing the \a cstr + /// string value in our global string pool. + /// + /// If the C string already exists in the global string pool, it + /// finds the current entry and returns the existing value. If it + /// doesn't exist, it is added to the string pool. + /// + /// @param[in] cstr + /// A NULL terminated C string to add to the string pool. + //------------------------------------------------------------------ + void + SetCString (const char *cstr); + + void + SetString (const llvm::StringRef &s); + + //------------------------------------------------------------------ + /// Set the C string value and its mangled counterpart. + /// + /// Object files and debug sybmols often use mangled string to + /// represent the linkage name for a symbol, function or global. + /// The string pool can efficiently store these values and their + /// counterparts so when we run into another instance of a mangled + /// name, we can avoid calling the name demangler over and over on + /// the same strings and then trying to unique them. + /// + /// @param[in] demangled + /// The demangled C string to correlate with the \a mangled + /// name. + /// + /// @param[in] mangled + /// The already uniqued mangled ConstString to correlate the + /// soon to be uniqued version of \a demangled. + //------------------------------------------------------------------ + void + SetCStringWithMangledCounterpart (const char *demangled, + const ConstString &mangled); + + //------------------------------------------------------------------ + /// Retrieve the mangled or demangled counterpart for a mangled + /// or demangled ConstString. + /// + /// Object files and debug sybmols often use mangled string to + /// represent the linkage name for a symbol, function or global. + /// The string pool can efficiently store these values and their + /// counterparts so when we run into another instance of a mangled + /// name, we can avoid calling the name demangler over and over on + /// the same strings and then trying to unique them. + /// + /// @param[in] counterpart + /// A reference to a ConstString object that might get filled in + /// with the demangled/mangled counterpart. + /// + /// @return + /// /b True if \a counterpart was filled in with the counterpart + /// /b false otherwise. + //------------------------------------------------------------------ + bool + GetMangledCounterpart (ConstString &counterpart) const; + + //------------------------------------------------------------------ + /// Set the C string value with length. + /// + /// Set the string value in the object by uniquing \a cstr_len bytes + /// starting at the \a cstr string value in our global string pool. + /// If trim is true, then \a cstr_len indicates a maximum length of + /// the CString and if the actual length of the string is less, then + /// it will be trimmed. + /// + /// If the C string already exists in the global string pool, it + /// finds the current entry and returns the existing value. If it + /// doesn't exist, it is added to the string pool. + /// + /// @param[in] cstr + /// A NULL terminated C string to add to the string pool. + /// + /// @param[in] cstr_len + /// The maximum length of the C string. + //------------------------------------------------------------------ + void + SetCStringWithLength (const char *cstr, size_t cstr_len); + + //------------------------------------------------------------------ + /// Set the C string value with the minimum length between + /// \a fixed_cstr_len and the actual length of the C string. This + /// can be used for data structures that have a fixed length to + /// store a C string where the string might not be NULL terminated + /// if the string takes the entire buffer. + //------------------------------------------------------------------ + void + SetTrimmedCStringWithLength (const char *cstr, size_t fixed_cstr_len); + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// Return the size in bytes that this object takes in memory. This + /// returns the size in bytes of this object, which does not include + /// any the shared string values it may refer to. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + size_t + MemorySize () const + { + return sizeof(ConstString); + } + + + //------------------------------------------------------------------ + /// Get the size in bytes of the current global string pool. + /// + /// Reports the the size in bytes of all shared C string values, + /// containers and any other values as a byte size for the + /// entire string pool. + /// + /// @return + /// The number of bytes that the global string pool occupies + /// in memory. + //------------------------------------------------------------------ + static size_t + StaticMemorySize (); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + const char *m_string; +}; + +//------------------------------------------------------------------ +/// Stream the string value \a str to the stream \a s +//------------------------------------------------------------------ +Stream& operator << (Stream& s, const ConstString& str); + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_ConstString_h_ diff --git a/include/lldb/Core/DataBuffer.h b/include/lldb/Core/DataBuffer.h new file mode 100644 index 0000000..e64245d --- /dev/null +++ b/include/lldb/Core/DataBuffer.h @@ -0,0 +1,94 @@ +//===-- DataBuffer.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_DataBuffer_h_ +#define liblldb_DataBuffer_h_ +#if defined(__cplusplus) + +#include <stdint.h> +#include <string.h> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class DataBuffer DataBuffer.h "lldb/Core/DataBuffer.h" +/// @brief A pure virtual protocol class for abstracted data buffers. +/// +/// DataBuffer is an abtract class that gets packaged into a shared pointer +/// that can use to implement various ways to store data (on the heap, +/// memory mapped, cached inferior memory). It gets used by DataExtractor +/// so many DataExtractor objects can share the same data and sub-ranges +/// of that shared data, and the last object that contains a reference +/// to the shared data will free it. +/// +/// Subclasses can implement as many different constructors or member +/// functions that allow data to be stored in the object's buffer prior +/// to handing the shared data to clients that use these buffers. +/// +/// All subclasses must override all of the pure virtual functions as +/// they are used by clients to access the data. Having a common +/// interface allows different ways of storing data, yet using it in +/// one common way. +/// +/// This class currently expects all data to be available without any +/// extra calls being made, but we can modify it to optionally get +/// data on demand with some extra function calls to load the data +/// before it gets accessed. +//---------------------------------------------------------------------- +class DataBuffer +{ +public: + //------------------------------------------------------------------ + /// Destructor + /// + /// The destructor is virtual as other classes will inherit from + /// this class and be downcast to the DataBuffer pure virtual + /// interface. The virtual destructor ensures that destructing the + /// base class will destruct the class that inherited from it + /// correctly. + //------------------------------------------------------------------ + virtual + ~DataBuffer() + { + } + + //------------------------------------------------------------------ + /// Get a pointer to the data. + /// + /// @return + /// A pointer to the bytes owned by this object, or NULL if the + /// object contains no bytes. + //------------------------------------------------------------------ + virtual uint8_t * + GetBytes () = 0; + + //------------------------------------------------------------------ + /// Get a const pointer to the data. + /// + /// @return + /// A const pointer to the bytes owned by this object, or NULL + /// if the object contains no bytes. + //------------------------------------------------------------------ + virtual const uint8_t * + GetBytes () const = 0; + + //------------------------------------------------------------------ + /// Get the number of bytes in the data buffer. + /// + /// @return + /// The number of bytes this object currently contains. + //------------------------------------------------------------------ + virtual lldb::offset_t + GetByteSize() const = 0; +}; + +} // namespace lldb_private + +#endif /// #if defined(__cplusplus) +#endif /// lldb_DataBuffer_h_ diff --git a/include/lldb/Core/DataBufferHeap.h b/include/lldb/Core/DataBufferHeap.h new file mode 100644 index 0000000..dac9a28 --- /dev/null +++ b/include/lldb/Core/DataBufferHeap.h @@ -0,0 +1,139 @@ +//===-- DataBufferHeap.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_DataBufferHeap_h_ +#define liblldb_DataBufferHeap_h_ +#if defined(__cplusplus) + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/DataBuffer.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class DataBufferHeap DataBufferHeap.h "lldb/Core/DataBufferHeap.h" +/// @brief A subclass of DataBuffer that stores a data buffer on the heap. +/// +/// This class keeps its data in a heap based buffer that is owned by +/// the object. This class is best used to store chunks of data that +/// are created or read from sources that can't intelligently and lazily +/// fault new data pages in. Large amounts of data that comes from files +/// should probably use the DataBufferMemoryMap class. +//---------------------------------------------------------------------- +class DataBufferHeap : public DataBuffer +{ +public: + //------------------------------------------------------------------ + /// Default constructor + /// + /// Initializes the heap based buffer with no bytes. + //------------------------------------------------------------------ + DataBufferHeap (); + + //------------------------------------------------------------------ + /// Construct with size \a n and fill with \a ch. + /// + /// Initialize this class with \a n bytes and fills the buffer with + /// \a ch. + /// + /// @param[in] n + /// The number of bytes that heap based buffer should contain. + /// + /// @param[in] ch + /// The character to use when filling the buffer initially. + //------------------------------------------------------------------ + DataBufferHeap (lldb::offset_t n, uint8_t ch); + + //------------------------------------------------------------------ + /// Construct by making a copy of \a src_len bytes from \a src. + /// + /// @param[in] src + /// A pointer to the data to copy. + /// + /// @param[in] src_len + /// The number of bytes in \a src to copy. + //------------------------------------------------------------------ + DataBufferHeap (const void *src, lldb::offset_t src_len); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// Virtual destructor since this class inherits from a pure virtual + /// base class #DataBuffer. + //------------------------------------------------------------------ + virtual + ~DataBufferHeap(); + + //------------------------------------------------------------------ + /// @copydoc DataBuffer::GetBytes() + //------------------------------------------------------------------ + virtual uint8_t * + GetBytes (); + + //------------------------------------------------------------------ + /// @copydoc DataBuffer::GetBytes() const + //------------------------------------------------------------------ + virtual const uint8_t * + GetBytes () const; + + //------------------------------------------------------------------ + /// @copydoc DataBuffer::GetByteSize() const + //------------------------------------------------------------------ + virtual lldb::offset_t + GetByteSize () const; + + //------------------------------------------------------------------ + /// Set the number of bytes in the data buffer. + /// + /// Sets the number of bytes that this object should be able to + /// contain. This can be used prior to copying data into the buffer. + /// + /// @param[in] byte_size + /// The new size in bytes that this data buffer should attempt + /// to resize itself to. + /// + /// @return + /// The size in bytes after that this heap buffer was + /// successfully resized to. + //------------------------------------------------------------------ + lldb::offset_t + SetByteSize (lldb::offset_t byte_size); + + //------------------------------------------------------------------ + /// Makes a copy of the \a src_len bytes in \a src. + /// + /// Copies the data in \a src into an internal buffer. + /// + /// @param[in] src + /// A pointer to the data to copy. + /// + /// @param[in] src_len + /// The number of bytes in \a src to copy. + //------------------------------------------------------------------ + void + CopyData (const void *src, lldb::offset_t src_len); + + void + Clear(); + +private: + //------------------------------------------------------------------ + // This object uses a std::vector<uint8_t> to store its data. This + // takes care of free the data when the object is deleted. + //------------------------------------------------------------------ + typedef std::vector<uint8_t> buffer_t; ///< Buffer type + buffer_t m_data; ///< The heap based buffer where data is stored +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_DataBufferHeap_h_ diff --git a/include/lldb/Core/DataBufferMemoryMap.h b/include/lldb/Core/DataBufferMemoryMap.h new file mode 100644 index 0000000..d4a448a --- /dev/null +++ b/include/lldb/Core/DataBufferMemoryMap.h @@ -0,0 +1,160 @@ +//===-- DataBufferMemoryMap.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_DataBufferMemoryMap_h_ +#define liblldb_DataBufferMemoryMap_h_ +#if defined(__cplusplus) + + +#include "lldb/lldb-private.h" +#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/Error.h" +#include <string> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class DataBufferMemoryMap DataBufferMemoryMap.h "lldb/Core/DataBufferMemoryMap.h" +/// @brief A subclass of DataBuffer that memory maps data. +/// +/// This class memory maps data and stores any needed data for the +/// memory mapping in its internal state. Memory map requests are not +/// required to have any alignment or size constraints, this class will +/// work around any host OS issues regarding such things. +/// +/// This class is designed to allow pages to be faulted in as needed and +/// works well data from large files that won't be accessed all at once. +//---------------------------------------------------------------------- +class DataBufferMemoryMap : public DataBuffer +{ +public: + //------------------------------------------------------------------ + /// Default Constructor + //------------------------------------------------------------------ + DataBufferMemoryMap (); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// Virtual destructor since this class inherits from a pure virtual + /// base class #DataBuffer. + //------------------------------------------------------------------ + virtual + ~DataBufferMemoryMap (); + + //------------------------------------------------------------------ + /// Reverts this object to an empty state by unmapping any memory + /// that is currently owned. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// @copydoc DataBuffer::GetBytes() + //------------------------------------------------------------------ + virtual uint8_t * + GetBytes (); + + //------------------------------------------------------------------ + /// @copydoc DataBuffer::GetBytes() const + //------------------------------------------------------------------ + virtual const uint8_t * + GetBytes () const; + + //------------------------------------------------------------------ + /// @copydoc DataBuffer::GetByteSize() const + //------------------------------------------------------------------ + virtual lldb::offset_t + GetByteSize () const; + + //------------------------------------------------------------------ + /// Error get accessor. + /// + /// @return + /// A const reference to Error object in case memory mapping + /// fails. + //------------------------------------------------------------------ + const Error & + GetError() const; + + //------------------------------------------------------------------ + /// Memory map all or part of a file. + /// + /// Memory map \a length bytes from \a file starting \a offset + /// bytes into the file. If \a length is set to \c SIZE_MAX, + /// then map as many bytes as possible. + /// + /// @param[in] file + /// The file specification from which to map data. + /// + /// @param[in] offset + /// The offset in bytes from the beginning of the file where + /// memory mapping should begin. + /// + /// @param[in] length + /// The size in bytes that should be mapped starting \a offset + /// bytes into the file. If \a length is \c SIZE_MAX, map + /// as many bytes as possible. + /// + /// @return + /// The number of bytes mapped starting from the \a offset. + //------------------------------------------------------------------ + size_t + MemoryMapFromFileSpec (const FileSpec* file, + lldb::offset_t offset = 0, + lldb::offset_t length = SIZE_MAX, + bool writeable = false); + + //------------------------------------------------------------------ + /// Memory map all or part of a file. + /// + /// Memory map \a length bytes from an opened file descriptor \a fd + /// starting \a offset bytes into the file. If \a length is set to + /// \c SIZE_MAX, then map as many bytes as possible. + /// + /// @param[in] fd + /// The posix file descriptor for an already opened file + /// from which to map data. + /// + /// @param[in] offset + /// The offset in bytes from the beginning of the file where + /// memory mapping should begin. + /// + /// @param[in] length + /// The size in bytes that should be mapped starting \a offset + /// bytes into the file. If \a length is \c SIZE_MAX, map + /// as many bytes as possible. + /// + /// @return + /// The number of bytes mapped starting from the \a offset. + //------------------------------------------------------------------ + size_t + MemoryMapFromFileDescriptor (int fd, + lldb::offset_t offset, + lldb::offset_t length, + bool write, + bool fd_is_file); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from DataBufferMemoryMap can see and modify these + //------------------------------------------------------------------ + uint8_t * m_mmap_addr; ///< The actual pointer that was returned from \c mmap() + size_t m_mmap_size; ///< The actual number of bytes that were mapped when \c mmap() was called + uint8_t *m_data; ///< The data the user requested somewhere within the memory mapped data. + lldb::offset_t m_size; ///< The size of the data the user got when data was requested + +private: + DISALLOW_COPY_AND_ASSIGN (DataBufferMemoryMap); +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_DataBufferMemoryMap_h_ diff --git a/include/lldb/Core/DataEncoder.h b/include/lldb/Core/DataEncoder.h new file mode 100644 index 0000000..658cce0 --- /dev/null +++ b/include/lldb/Core/DataEncoder.h @@ -0,0 +1,459 @@ +//===-- DataEncoder.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_DataEncoder_h_ +#define liblldb_DataEncoder_h_ + +#if defined (__cplusplus) + +#include "lldb/lldb-private.h" +#include <limits.h> +#include <stdint.h> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class DataEncoder DataEncoder.h "lldb/Core/DataEncoder.h" +/// @brief An binary data encoding class. +/// +/// DataEncoder is a class that can encode binary data (swapping if needed) +/// to a data buffer. The data buffer can be caller owned, or can be +/// shared data that can be shared between multiple DataEncoder or +/// DataEncoder instances. +/// +/// @see DataBuffer +//---------------------------------------------------------------------- +class DataEncoder +{ +public: + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize all members to a default empty state. + //------------------------------------------------------------------ + DataEncoder (); + + //------------------------------------------------------------------ + /// Construct with a buffer that is owned by the caller. + /// + /// This constructor allows us to use data that is owned by the + /// caller. The data must stay around as long as this object is + /// valid. + /// + /// @param[in] data + /// A pointer to caller owned data. + /// + /// @param[in] data_length + /// The length in bytes of \a data. + /// + /// @param[in] byte_order + /// A byte order of the data that we are extracting from. + /// + /// @param[in] addr_size + /// A new address byte size value. + //------------------------------------------------------------------ + DataEncoder (void* data, uint32_t data_length, lldb::ByteOrder byte_order, uint8_t addr_size); + + //------------------------------------------------------------------ + /// Construct with shared data. + /// + /// Copies the data shared pointer which adds a reference to the + /// contained in \a data_sp. The shared data reference is reference + /// counted to ensure the data lives as long as anyone still has a + /// valid shared pointer to the data in \a data_sp. + /// + /// @param[in] data_sp + /// A shared pointer to data. + /// + /// @param[in] byte_order + /// A byte order of the data that we are extracting from. + /// + /// @param[in] addr_size + /// A new address byte size value. + //------------------------------------------------------------------ + DataEncoder (const lldb::DataBufferSP& data_sp, lldb::ByteOrder byte_order, uint8_t addr_size); + + //------------------------------------------------------------------ + /// Destructor + /// + /// If this object contains a valid shared data reference, the + /// reference count on the data will be decremented, and if zero, + /// the data will be freed. + //------------------------------------------------------------------ + ~DataEncoder (); + + //------------------------------------------------------------------ + /// Clears the object state. + /// + /// Clears the object contents back to a default invalid state, and + /// release any references to shared data that this object may + /// contain. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Get the current address size. + /// + /// Return the size in bytes of any address values this object will + /// extract. + /// + /// @return + /// The size in bytes of address values that will be extracted. + //------------------------------------------------------------------ + uint8_t + GetAddressByteSize () const + { + return m_addr_size; + } + + + //------------------------------------------------------------------ + /// Get the number of bytes contained in this object. + /// + /// @return + /// The total number of bytes of data this object refers to. + //------------------------------------------------------------------ + size_t + GetByteSize () const + { + return m_end - m_start; + } + + //------------------------------------------------------------------ + /// Get the data end pointer. + /// + /// @return + /// Returns a pointer to the next byte contained in this + /// object's data, or NULL of there is no data in this object. + //------------------------------------------------------------------ + uint8_t * + GetDataEnd () + { + return m_end; + } + + const uint8_t * + GetDataEnd () const + { + return m_end; + } + + //------------------------------------------------------------------ + /// Get the shared data offset. + /// + /// Get the offset of the first byte of data in the shared data (if + /// any). + /// + /// @return + /// If this object contains shared data, this function returns + /// the offset in bytes into that shared data, zero otherwise. + //------------------------------------------------------------------ + size_t + GetSharedDataOffset () const; + + + //------------------------------------------------------------------ + /// Get the current byte order value. + /// + /// @return + /// The current byte order value from this object's internal + /// state. + //------------------------------------------------------------------ + lldb::ByteOrder + GetByteOrder() const + { + return m_byte_order; + } + + //------------------------------------------------------------------ + /// Get a the data start pointer. + /// + /// @return + /// Returns a pointer to the first byte contained in this + /// object's data, or NULL of there is no data in this object. + //------------------------------------------------------------------ + uint8_t * + GetDataStart () + { + return m_start; + } + + const uint8_t * + GetDataStart () const + { + return m_start; + } + + //------------------------------------------------------------------ + /// Encode unsigned integer values into the data at \a offset. + /// + /// @param[in] offset + /// The offset within the contained data at which to put the + /// data. + /// + /// @param[in] value + /// The value to encode into the data. + /// + /// @return + /// The next offset in the bytes of this data if the data + /// was successfully encoded, UINT32_MAX if the encoding failed. + //------------------------------------------------------------------ + uint32_t + PutU8 (uint32_t offset, uint8_t value); + + uint32_t + PutU16 (uint32_t offset, uint16_t value); + + uint32_t + PutU32 (uint32_t offset, uint32_t value); + + uint32_t + PutU64 (uint32_t offset, uint64_t value); + + //------------------------------------------------------------------ + /// Encode an unsigned integer of size \a byte_size to \a offset. + /// + /// Encode a single integer value at \a offset and return the offset + /// that follows the newly encoded integer when the data is successfully + /// encoded into the existing data. There must be enough room in the + /// data, else UINT32_MAX will be returned to indicate that encoding + /// failed. + /// + /// @param[in] offset + /// The offset within the contained data at which to put the + /// encoded integer. + /// + /// @param[in] byte_size + /// The size in byte of the integer to encode. + /// + /// @param[in] value + /// The integer value to write. The least significate bytes of + /// the integer value will be written if the size is less than + /// 8 bytes. + /// + /// @return + /// The next offset in the bytes of this data if the integer + /// was successfully encoded, UINT32_MAX if the encoding failed. + //------------------------------------------------------------------ + uint32_t + PutMaxU64 (uint32_t offset, uint32_t byte_size, uint64_t value); + + //------------------------------------------------------------------ + /// Encode an arbitrary number of bytes. + /// + /// @param[in] offset + /// The offset in bytes into the contained data at which to + /// start encoding. + /// + /// @param[int] src + /// The buffer that contains the the bytes to encode. + /// + /// @param[in] src_len + /// The number of bytes to encode. + /// + /// @return + /// The next valid offset within data if the put operation + /// was successful, else UINT32_MAX to indicate the put failed. + //------------------------------------------------------------------ + uint32_t + PutData (uint32_t offset, + const void *src, + uint32_t src_len); + + //------------------------------------------------------------------ + /// Encode an address in the existing buffer at \a offset bytes into + /// the buffer. + /// + /// Encode a single address (honoring the m_addr_size member) to + /// the data and return the next offset where subsequent data would + /// go. + /// pointed to by \a offset_ptr. The size of the extracted address + /// comes from the \a m_addr_size member variable and should be + /// set correctly prior to extracting any address values. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The next valid offset within data if the put operation + /// was successful, else UINT32_MAX to indicate the put failed. + //------------------------------------------------------------------ + uint32_t + PutAddress (uint32_t offset, lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Put a C string to \a offset. + /// + /// Encodes a C string into the existing data including the + /// terminating + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// A pointer to the C string value in the data. If the offset + /// pointed to by \a offset_ptr is out of bounds, or if the + /// offset plus the length of the C string is out of bounds, + /// NULL will be returned. + //------------------------------------------------------------------ + uint32_t + PutCString (uint32_t offset_ptr, const char *cstr); + + lldb::DataBufferSP & + GetSharedDataBuffer () + { + return m_data_sp; + } + + //------------------------------------------------------------------ + /// Set the address byte size. + /// + /// Set the size in bytes that will be used when extracting any + /// address and pointer values from data contained in this object. + /// + /// @param[in] addr_size + /// The size in bytes to use when extracting addresses. + //------------------------------------------------------------------ + void + SetAddressByteSize (uint8_t addr_size) + { + m_addr_size = addr_size; + } + + //------------------------------------------------------------------ + /// Set data with a buffer that is caller owned. + /// + /// Use data that is owned by the caller when extracting values. + /// The data must stay around as long as this object, or any object + /// that copies a subset of this object's data, is valid. If \a + /// bytes is NULL, or \a length is zero, this object will contain + /// no data. + /// + /// @param[in] bytes + /// A pointer to caller owned data. + /// + /// @param[in] length + /// The length in bytes of \a bytes. + /// + /// @param[in] byte_order + /// A byte order of the data that we are extracting from. + /// + /// @return + /// The number of bytes that this object now contains. + //------------------------------------------------------------------ + uint32_t + SetData (const void *bytes, uint32_t length, lldb::ByteOrder byte_order); + + //------------------------------------------------------------------ + /// Adopt a subset of shared data in \a data_sp. + /// + /// Copies the data shared pointer which adds a reference to the + /// contained in \a data_sp. The shared data reference is reference + /// counted to ensure the data lives as long as anyone still has a + /// valid shared pointer to the data in \a data_sp. The byte order + /// and address byte size settings remain the same. If + /// \a offset is not a valid offset in \a data_sp, then no reference + /// to the shared data will be added. If there are not \a length + /// bytes available in \a data starting at \a offset, the length + /// will be truncated to contains as many bytes as possible. + /// + /// @param[in] data_sp + /// A shared pointer to data. + /// + /// @param[in] offset + /// The offset into \a data_sp at which the subset starts. + /// + /// @param[in] length + /// The length in bytes of the subset of \a data_sp. + /// + /// @return + /// The number of bytes that this object now contains. + //------------------------------------------------------------------ + uint32_t + SetData (const lldb::DataBufferSP& data_sp, uint32_t offset = 0, uint32_t length = UINT32_MAX); + + //------------------------------------------------------------------ + /// Set the byte_order value. + /// + /// Sets the byte order of the data to extract. Extracted values + /// will be swapped if necessary when decoding. + /// + /// @param[in] byte_order + /// The byte order value to use when extracting data. + //------------------------------------------------------------------ + void + SetByteOrder (lldb::ByteOrder byte_order) + { + m_byte_order = byte_order; + } + + + //------------------------------------------------------------------ + /// Test the validity of \a offset. + /// + /// @return + /// \b true if \a offset is a valid offset into the data in this + /// object, \b false otherwise. + //------------------------------------------------------------------ + bool + ValidOffset (uint32_t offset) const + { + return offset < GetByteSize(); + } + + //------------------------------------------------------------------ + /// Test the availability of \a length bytes of data from \a offset. + /// + /// @return + /// \b true if \a offset is a valid offset and there are \a + /// length bytes available at that offset, \b false otherwise. + //------------------------------------------------------------------ + bool + ValidOffsetForDataOfSize (uint32_t offset, uint32_t length) const + { + return length <= BytesLeft (offset); + } + + uint32_t + BytesLeft (uint32_t offset) const + { + const uint32_t size = GetByteSize(); + if (size > offset) + return size - offset; + return 0; + } + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + uint8_t *m_start; ///< A pointer to the first byte of data. + uint8_t *m_end; ///< A pointer to the byte that is past the end of the data. + lldb::ByteOrder m_byte_order; ///< The byte order of the data we are extracting from. + uint8_t m_addr_size; ///< The address size to use when extracting pointers or addresses + mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can be shared among multilple instances + +private: + DISALLOW_COPY_AND_ASSIGN (DataEncoder); + +}; + +} // namespace lldb_private + +#endif // #if defined (__cplusplus) +#endif // #ifndef liblldb_DataEncoder_h_ diff --git a/include/lldb/Core/DataExtractor.h b/include/lldb/Core/DataExtractor.h new file mode 100644 index 0000000..a859304 --- /dev/null +++ b/include/lldb/Core/DataExtractor.h @@ -0,0 +1,1298 @@ +//===-- DataExtractor.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_DataExtractor_h_ +#define liblldb_DataExtractor_h_ +#if defined (__cplusplus) + + +#include "lldb/lldb-private.h" +#include <limits.h> +#include <stdint.h> +#include <string.h> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class DataExtractor DataExtractor.h "lldb/Core/DataExtractor.h" +/// @brief An data extractor class. +/// +/// DataExtractor is a class that can extract data (swapping if needed) +/// from a data buffer. The data buffer can be caller owned, or can be +/// shared data that can be shared between multiple DataExtractor +/// instances. Multiple DataExtractor objects can share the same data, +/// yet extract values in different address sizes and byte order modes. +/// Each object can have a unique position in the shared data and extract +/// data from different offsets. +/// +/// @see DataBuffer +//---------------------------------------------------------------------- +class DataExtractor +{ +public: + //------------------------------------------------------------------ + /// @typedef DataExtractor::Type + /// @brief Type enumerations used in the dump routines. + /// @see DataExtractor::Dump() + /// @see DataExtractor::DumpRawHexBytes() + //------------------------------------------------------------------ + typedef enum + { + TypeUInt8, ///< Format output as unsigned 8 bit integers + TypeChar, ///< Format output as characters + TypeUInt16, ///< Format output as unsigned 16 bit integers + TypeUInt32, ///< Format output as unsigned 32 bit integers + TypeUInt64, ///< Format output as unsigned 64 bit integers + TypePointer, ///< Format output as pointers + TypeULEB128, ///< Format output as ULEB128 numbers + TypeSLEB128 ///< Format output as SLEB128 numbers + } Type; + + static void + DumpHexBytes (Stream *s, + const void *src, + size_t src_len, + uint32_t bytes_per_line, + lldb::addr_t base_addr); // Pass LLDB_INVALID_ADDRESS to not show address at start of line + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize all members to a default empty state. + //------------------------------------------------------------------ + DataExtractor (); + + //------------------------------------------------------------------ + /// Construct with a buffer that is owned by the caller. + /// + /// This constructor allows us to use data that is owned by the + /// caller. The data must stay around as long as this object is + /// valid. + /// + /// @param[in] data + /// A pointer to caller owned data. + /// + /// @param[in] data_length + /// The length in bytes of \a data. + /// + /// @param[in] byte_order + /// A byte order of the data that we are extracting from. + /// + /// @param[in] addr_size + /// A new address byte size value. + //------------------------------------------------------------------ + DataExtractor (const void* data, lldb::offset_t data_length, lldb::ByteOrder byte_order, uint32_t addr_size); + + //------------------------------------------------------------------ + /// Construct with shared data. + /// + /// Copies the data shared pointer which adds a reference to the + /// contained in \a data_sp. The shared data reference is reference + /// counted to ensure the data lives as long as anyone still has a + /// valid shared pointer to the data in \a data_sp. + /// + /// @param[in] data_sp + /// A shared pointer to data. + /// + /// @param[in] byte_order + /// A byte order of the data that we are extracting from. + /// + /// @param[in] addr_size + /// A new address byte size value. + //------------------------------------------------------------------ + DataExtractor (const lldb::DataBufferSP& data_sp, lldb::ByteOrder byte_order, uint32_t addr_size); + + //------------------------------------------------------------------ + /// Construct with a subset of \a data. + /// + /// Initialize this object with a subset of the data bytes in \a + /// data. If \a data contains shared data, then a reference to the + /// shared data will be added to ensure the shared data stays around + /// as long as any objects have references to the shared data. The + /// byte order value and the address size settings are copied from \a + /// data. If \a offset is not a valid offset in \a data, then no + /// reference to the shared data will be added. If there are not + /// \a length bytes available in \a data starting at \a offset, + /// the length will be truncated to contain as many bytes as + /// possible. + /// + /// @param[in] data + /// Another DataExtractor object that contains data. + /// + /// @param[in] offset + /// The offset into \a data at which the subset starts. + /// + /// @param[in] length + /// The length in bytes of the subset of data. + //------------------------------------------------------------------ + DataExtractor (const DataExtractor& data, lldb::offset_t offset, lldb::offset_t length); + + DataExtractor (const DataExtractor& rhs); + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// Copies all data, byte order and address size settings from \a rhs into + /// this object. If \a rhs contains shared data, a reference to that + /// shared data will be added. + /// + /// @param[in] rhs + /// Another DataExtractor object to copy. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const DataExtractor& + operator= (const DataExtractor& rhs); + + //------------------------------------------------------------------ + /// Destructor + /// + /// If this object contains a valid shared data reference, the + /// reference count on the data will be decremented, and if zero, + /// the data will be freed. + //------------------------------------------------------------------ + ~DataExtractor (); + + //------------------------------------------------------------------ + /// Clears the object state. + /// + /// Clears the object contents back to a default invalid state, and + /// release any references to shared data that this object may + /// contain. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Dumps the binary data as \a type objects to stream \a s (or to + /// Log() if \a s is NULL) starting \a offset bytes into the data + /// and stopping after dumping \a length bytes. The offset into the + /// data is displayed at the beginning of each line and can be + /// offset by base address \a base_addr. \a num_per_line objects + /// will be displayed on each line. + /// + /// @param[in] s + /// The stream to dump the output to. If NULL the output will + /// be dumped to Log(). + /// + /// @param[in] offset + /// The offset into the data at which to start dumping. + /// + /// @param[in] length + /// The number of bytes to dump. + /// + /// @param[in] base_addr + /// The base address that gets added to the offset displayed on + /// each line. + /// + /// @param[in] num_per_line + /// The number of \a type objects to display on each line. + /// + /// @param[in] type + /// The type of objects to use when dumping data from this + /// object. See DataExtractor::Type. + /// + /// @param[in] type_format + /// The optional format to use for the \a type objects. If this + /// is NULL, the default format for the \a type will be used. + /// + /// @return + /// The offset at which dumping ended. + //------------------------------------------------------------------ + lldb::offset_t + PutToLog (Log *log, + lldb::offset_t offset, + lldb::offset_t length, + uint64_t base_addr, + uint32_t num_per_line, + Type type, + const char *type_format = NULL) const; + + //------------------------------------------------------------------ + /// Dumps \a item_count objects into the stream \a s. + /// + /// Dumps \a item_count objects using \a item_format, each of which + /// are \a item_byte_size bytes long starting at offset \a offset + /// bytes into the contained data, into the stream \a s. \a + /// num_per_line objects will be dumped on each line before a new + /// line will be output. If \a base_addr is a valid address, then + /// each new line of output will be prededed by the address value + /// plus appropriate offset, and a colon and space. Bitfield values + /// can be dumped by calling this function multiple times with the + /// same start offset, format and size, yet differing \a + /// item_bit_size and \a item_bit_offset values. + /// + /// @param[in] s + /// The stream to dump the output to. This value can not be NULL. + /// + /// @param[in] offset + /// The offset into the data at which to start dumping. + /// + /// @param[in] item_format + /// The format to use when dumping each item. + /// + /// @param[in] item_byte_size + /// The byte size of each item. + /// + /// @param[in] item_count + /// The number of items to dump. + /// + /// @param[in] num_per_line + /// The number of items to display on each line. + /// + /// @param[in] base_addr + /// The base address that gets added to the offset displayed on + /// each line if the value is valid. Is \a base_addr is + /// LLDB_INVALID_ADDRESS then no address values will be prepended + /// to any lines. + /// + /// @param[in] item_bit_size + /// If the value to display is a bitfield, this value should + /// be the number of bits that the bitfield item has within the + /// item's byte size value. This function will need to be called + /// multiple times with identical \a offset and \a item_byte_size + /// values in order to display multiple bitfield values that + /// exist within the same integer value. If the items being + /// displayed are not bitfields, this value should be zero. + /// + /// @param[in] item_bit_offset + /// If the value to display is a bitfield, this value should + /// be the offset in bits, or shift right amount, that the + /// bitfield item occupies within the item's byte size value. + /// This function will need to be called multiple times with + /// identical \a offset and \a item_byte_size values in order + /// to display multiple bitfield values that exist within the + /// same integer value. If the items being displayed are not + /// bitfields, this value should be zero. + /// + /// @return + /// The offset at which dumping ended. + //------------------------------------------------------------------ + lldb::offset_t + Dump (Stream *s, + lldb::offset_t offset, + lldb::Format item_format, + size_t item_byte_size, + size_t item_count, + size_t num_per_line, + uint64_t base_addr, + uint32_t item_bit_size, + uint32_t item_bit_offset, + ExecutionContextScope *exe_scope = NULL) const; + + //------------------------------------------------------------------ + /// Dump a UUID value at \a offset. + /// + /// Dump a UUID starting at \a offset bytes into this object's data. + /// If the stream \a s is NULL, the output will be sent to Log(). + /// + /// @param[in] s + /// The stream to dump the output to. If NULL the output will + /// be dumped to Log(). + /// + /// @param[in] offset + /// The offset into the data at which to extract and dump a + /// UUID value. + //------------------------------------------------------------------ + void + DumpUUID (Stream *s, lldb::offset_t offset) const; + + //------------------------------------------------------------------ + /// Extract an arbitrary number of bytes in the specified byte + /// order. + /// + /// Attemps to extract \a length bytes starting at \a offset bytes + /// into this data in the requested byte order (\a dst_byte_order) + /// and place the results in \a dst. \a dst must be at least \a + /// length bytes long. + /// + /// @param[in] offset + /// The offset in bytes into the contained data at which to + /// start extracting. + /// + /// @param[in] length + /// The number of bytes to extract. + /// + /// @param[in] dst_byte_order + /// A byte order of the data that we want when the value in + /// copied to \a dst. + /// + /// @param[out] dst + /// The buffer that will receive the extracted value if there + /// are enough bytes available in the current data. + /// + /// @return + /// The number of bytes that were extracted which will be \a + /// length when the value is successfully extracted, or zero + /// if there aren't enough bytes at the specified offset. + //------------------------------------------------------------------ + size_t + ExtractBytes (lldb::offset_t offset, lldb::offset_t length, lldb::ByteOrder dst_byte_order, void *dst) const; + + //------------------------------------------------------------------ + /// Extract an address from \a *offset_ptr. + /// + /// Extract a single address from the data and update the offset + /// pointed to by \a offset_ptr. The size of the extracted address + /// comes from the \a m_addr_size member variable and should be + /// set correctly prior to extracting any address values. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted address value. + //------------------------------------------------------------------ + uint64_t + GetAddress (lldb::offset_t *offset_ptr) const; + + uint64_t + GetAddress_unchecked (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Get the current address size. + /// + /// Return the size in bytes of any address values this object will + /// extract. + /// + /// @return + /// The size in bytes of address values that will be extracted. + //------------------------------------------------------------------ + uint32_t + GetAddressByteSize () const + { + return m_addr_size; + } + + //------------------------------------------------------------------ + /// Get the number of bytes contained in this object. + /// + /// @return + /// The total number of bytes of data this object refers to. + //------------------------------------------------------------------ + uint64_t + GetByteSize () const + { + return m_end - m_start; + } + + //------------------------------------------------------------------ + /// Extract a C string from \a *offset_ptr. + /// + /// Returns a pointer to a C String from the data at the offset + /// pointed to by \a offset_ptr. A variable length NULL terminated C + /// string will be extracted and the \a offset_ptr will be + /// updated with the offset of the byte that follows the NULL + /// terminator byte. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// A pointer to the C string value in the data. If the offset + /// pointed to by \a offset_ptr is out of bounds, or if the + /// offset plus the length of the C string is out of bounds, + /// NULL will be returned. + //------------------------------------------------------------------ + const char * + GetCStr (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Extract a C string from \a *offset_ptr with field size \a len. + /// + /// Returns a pointer to a C String from the data at the offset + /// pointed to by \a offset_ptr, with a field length of \a len. + /// A NULL terminated C string will be extracted and the \a offset_ptr + /// will be updated with the offset of the byte that follows the fixed + /// length field. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// A pointer to the C string value in the data. If the offset + /// pointed to by \a offset_ptr is out of bounds, or if the + /// offset plus the length of the field is out of bounds, or if + /// the field does not contain a NULL terminator byte, NULL will + /// be returned. + const char * + GetCStr (lldb::offset_t *offset_ptr, lldb::offset_t len) const; + + //------------------------------------------------------------------ + /// Extract \a length bytes from \a *offset_ptr. + /// + /// Returns a pointer to a bytes in this object's data at the offset + /// pointed to by \a offset_ptr. If \a length is zero or too large, + /// then the offset pointed to by \a offset_ptr will not be updated + /// and NULL will be returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] length + /// The optional length of a string to extract. If the value is + /// zero, a NULL terminated C string will be extracted. + /// + /// @return + /// A pointer to the bytes in this object's data if the offset + /// and length are valid, or NULL otherwise. + //------------------------------------------------------------------ + const void* + GetData (lldb::offset_t *offset_ptr, lldb::offset_t length) const + { + const uint8_t *ptr = PeekData (*offset_ptr, length); + if (ptr) + *offset_ptr += length; + return ptr; + } + + //------------------------------------------------------------------ + /// Copy \a dst_len bytes from \a *offset_ptr and ensure the copied + /// data is treated as a value that can be swapped to match the + /// specified byte order. + /// + /// For values that are larger than the supported integer sizes, + /// this function can be used to extract data in a specified byte + /// order. It can also be used to copy a smaller integer value from + /// to a larger value. The extra bytes left over will be padded + /// correctly according to the byte order of this object and the + /// \a dst_byte_order. This can be very handy when say copying a + /// partial data value into a register. + /// + /// @param[in] src_offset + /// The offset into this data from which to start copying an + /// endian entity + /// + /// @param[in] src_len + /// The length of the endian data to copy from this object + /// into the \a dst object + /// + /// @param[out] dst + /// The buffer where to place the endian data. The data might + /// need to be byte swapped (and appropriately padded with + /// zeroes if \a src_len != \a dst_len) if \a dst_byte_order + /// does not match the byte order in this object. + /// + /// @param[in] dst_len + /// The length number of bytes that the endian value will + /// occupy is \a dst. + /// + /// @param[in] byte_order + /// The byte order that the endian value should be in the \a dst + /// buffer. + /// + /// @return + /// Returns the number of bytes that were copied, or zero if + /// anything goes wrong. + //------------------------------------------------------------------ + lldb::offset_t + CopyByteOrderedData (lldb::offset_t src_offset, + lldb::offset_t src_len, + void *dst, + lldb::offset_t dst_len, + lldb::ByteOrder dst_byte_order) const; + + //------------------------------------------------------------------ + /// Get the data end pointer. + /// + /// @return + /// Returns a pointer to the next byte contained in this + /// object's data, or NULL of there is no data in this object. + //------------------------------------------------------------------ + const uint8_t * + GetDataEnd () const + { + return m_end; + } + + //------------------------------------------------------------------ + /// Get the shared data offset. + /// + /// Get the offset of the first byte of data in the shared data (if + /// any). + /// + /// @return + /// If this object contains shared data, this function returns + /// the offset in bytes into that shared data, zero otherwise. + //------------------------------------------------------------------ + size_t + GetSharedDataOffset () const; + + //------------------------------------------------------------------ + /// Get a the data start pointer. + /// + /// @return + /// Returns a pointer to the first byte contained in this + /// object's data, or NULL of there is no data in this object. + //------------------------------------------------------------------ + const uint8_t * + GetDataStart () const + { + return m_start; + } + + + //------------------------------------------------------------------ + /// Extract a float from \a *offset_ptr. + /// + /// Extract a single float value. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The floating value that was extracted, or zero on failure. + //------------------------------------------------------------------ + float + GetFloat (lldb::offset_t *offset_ptr) const; + + double + GetDouble (lldb::offset_t *offset_ptr) const; + + long double + GetLongDouble (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Extract a GNU encoded pointer value from \a *offset_ptr. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] eh_ptr_enc + /// The GNU pointer encoding type. + /// + /// @param[in] pc_rel_addr + /// The PC relative address to use when the encoding is + /// \c DW_GNU_EH_PE_pcrel. + /// + /// @param[in] text_addr + /// The text (code) relative address to use when the encoding is + /// \c DW_GNU_EH_PE_textrel. + /// + /// @param[in] data_addr + /// The data relative address to use when the encoding is + /// \c DW_GNU_EH_PE_datarel. + /// + /// @return + /// The extracted GNU encoded pointer value. + //------------------------------------------------------------------ + uint64_t + GetGNUEHPointer (lldb::offset_t *offset_ptr, + uint32_t eh_ptr_enc, + lldb::addr_t pc_rel_addr, + lldb::addr_t text_addr, + lldb::addr_t data_addr); + + //------------------------------------------------------------------ + /// Extract an integer of size \a byte_size from \a *offset_ptr. + /// + /// Extract a single integer value and update the offset pointed to + /// by \a offset_ptr. The size of the extracted integer is specified + /// by the \a byte_size argument. \a byte_size should have a value + /// >= 1 and <= 4 since the return value is only 32 bits wide. Any + /// \a byte_size values less than 1 or greater than 4 will result in + /// nothing being extracted, and zero being returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] byte_size + /// The size in byte of the integer to extract. + /// + /// @return + /// The integer value that was extracted, or zero on failure. + //------------------------------------------------------------------ + uint32_t + GetMaxU32 (lldb::offset_t *offset_ptr, size_t byte_size) const; + + //------------------------------------------------------------------ + /// Extract an unsigned integer of size \a byte_size from \a + /// *offset_ptr. + /// + /// Extract a single unsigned integer value and update the offset + /// pointed to by \a offset_ptr. The size of the extracted integer + /// is specified by the \a byte_size argument. \a byte_size should + /// have a value greater than or equal to one and less than or equal + /// to eight since the return value is 64 bits wide. Any + /// \a byte_size values less than 1 or greater than 8 will result in + /// nothing being extracted, and zero being returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] byte_size + /// The size in byte of the integer to extract. + /// + /// @return + /// The unsigned integer value that was extracted, or zero on + /// failure. + //------------------------------------------------------------------ + uint64_t + GetMaxU64 (lldb::offset_t *offset_ptr, size_t byte_size) const; + + uint64_t + GetMaxU64_unchecked (lldb::offset_t *offset_ptr, size_t byte_size) const; + + //------------------------------------------------------------------ + /// Extract an signed integer of size \a byte_size from \a *offset_ptr. + /// + /// Extract a single signed integer value (sign extending if required) + /// and update the offset pointed to by \a offset_ptr. The size of + /// the extracted integer is specified by the \a byte_size argument. + /// \a byte_size should have a value greater than or equal to one + /// and less than or equal to eight since the return value is 64 + /// bits wide. Any \a byte_size values less than 1 or greater than + /// 8 will result in nothing being extracted, and zero being returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] byte_size + /// The size in byte of the integer to extract. + /// + /// @return + /// The sign extended signed integer value that was extracted, + /// or zero on failure. + //------------------------------------------------------------------ + int64_t + GetMaxS64 (lldb::offset_t *offset_ptr, size_t size) const; + + //------------------------------------------------------------------ + /// Extract an unsigned integer of size \a byte_size from \a + /// *offset_ptr, then extract the bitfield from this value if + /// \a bitfield_bit_size is non-zero. + /// + /// Extract a single unsigned integer value and update the offset + /// pointed to by \a offset_ptr. The size of the extracted integer + /// is specified by the \a byte_size argument. \a byte_size should + /// have a value greater than or equal to one and less than or equal + /// to 8 since the return value is 64 bits wide. Any + /// \a byte_size values less than 1 or greater than 8 will result in + /// nothing being extracted, and zero being returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] byte_size + /// The size in byte of the integer to extract. + /// + /// @param[in] bitfield_bit_size + /// The size in bits of the bitfield value to extract, or zero + /// to just extract the entire integer value. + /// + /// @param[in] bitfield_bit_offset + /// The bit offset of the bitfield value in the extracted + /// integer (the number of bits to shift the integer to the + /// right). + /// + /// @return + /// The unsigned bitfield integer value that was extracted, or + /// zero on failure. + //------------------------------------------------------------------ + uint64_t + GetMaxU64Bitfield (lldb::offset_t *offset_ptr, + size_t size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset) const; + + //------------------------------------------------------------------ + /// Extract an signed integer of size \a byte_size from \a + /// *offset_ptr, then extract and signe extend the bitfield from + /// this value if \a bitfield_bit_size is non-zero. + /// + /// Extract a single signed integer value (sign extending if required) + /// and update the offset pointed to by \a offset_ptr. The size of + /// the extracted integer is specified by the \a byte_size argument. + /// \a byte_size should have a value greater than or equal to one + /// and less than or equal to eight since the return value is 64 + /// bits wide. Any \a byte_size values less than 1 or greater than + /// 8 will result in nothing being extracted, and zero being returned. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[in] byte_size + /// The size in bytes of the integer to extract. + /// + /// @param[in] bitfield_bit_size + /// The size in bits of the bitfield value to extract, or zero + /// to just extract the entire integer value. + /// + /// @param[in] bitfield_bit_offset + /// The bit offset of the bitfield value in the extracted + /// integer (the number of bits to shift the integer to the + /// right). + /// + /// @return + /// The signed bitfield integer value that was extracted, or + /// zero on failure. + //------------------------------------------------------------------ + int64_t + GetMaxS64Bitfield (lldb::offset_t *offset_ptr, + size_t size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset) const; + + //------------------------------------------------------------------ + /// Extract an pointer from \a *offset_ptr. + /// + /// Extract a single pointer from the data and update the offset + /// pointed to by \a offset_ptr. The size of the extracted pointer + /// comes from the \a m_addr_size member variable and should be + /// set correctly prior to extracting any pointer values. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted pointer value as a 64 integer. + //------------------------------------------------------------------ + uint64_t + GetPointer (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Get the current byte order value. + /// + /// @return + /// The current byte order value from this object's internal + /// state. + //------------------------------------------------------------------ + lldb::ByteOrder + GetByteOrder() const + { + return m_byte_order; + } + + //------------------------------------------------------------------ + /// Extract a uint8_t value from \a *offset_ptr. + /// + /// Extract a single uint8_t from the binary data at the offset + /// pointed to by \a offset_ptr, and advance the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint8_t value. + //------------------------------------------------------------------ + uint8_t + GetU8 ( lldb::offset_t *offset_ptr) const; + + uint8_t + GetU8_unchecked (lldb::offset_t *offset_ptr) const + { + uint8_t val = m_start[*offset_ptr]; + *offset_ptr += 1; + return val; + } + + uint16_t + GetU16_unchecked (lldb::offset_t *offset_ptr) const; + + uint32_t + GetU32_unchecked (lldb::offset_t *offset_ptr) const; + + uint64_t + GetU64_unchecked (lldb::offset_t *offset_ptr) const; + //------------------------------------------------------------------ + /// Extract \a count uint8_t values from \a *offset_ptr. + /// + /// Extract \a count uint8_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint8_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint8_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + //------------------------------------------------------------------ + void * + GetU8 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; + + //------------------------------------------------------------------ + /// Extract a uint16_t value from \a *offset_ptr. + /// + /// Extract a single uint16_t from the binary data at the offset + /// pointed to by \a offset_ptr, and update the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint16_t value. + //------------------------------------------------------------------ + uint16_t + GetU16 (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Extract \a count uint16_t values from \a *offset_ptr. + /// + /// Extract \a count uint16_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint16_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint16_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + //------------------------------------------------------------------ + void * + GetU16 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; + + //------------------------------------------------------------------ + /// Extract a uint32_t value from \a *offset_ptr. + /// + /// Extract a single uint32_t from the binary data at the offset + /// pointed to by \a offset_ptr, and update the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint32_t value. + //------------------------------------------------------------------ + uint32_t + GetU32 (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Extract \a count uint32_t values from \a *offset_ptr. + /// + /// Extract \a count uint32_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint32_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint32_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + //------------------------------------------------------------------ + void * + GetU32 (lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; + + //------------------------------------------------------------------ + /// Extract a uint64_t value from \a *offset_ptr. + /// + /// Extract a single uint64_t from the binary data at the offset + /// pointed to by \a offset_ptr, and update the offset on success. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted uint64_t value. + //------------------------------------------------------------------ + uint64_t + GetU64 (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Extract \a count uint64_t values from \a *offset_ptr. + /// + /// Extract \a count uint64_t values from the binary data at the + /// offset pointed to by \a offset_ptr, and advance the offset on + /// success. The extracted values are copied into \a dst. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @param[out] dst + /// A buffer to copy \a count uint64_t values into. \a dst must + /// be large enough to hold all requested data. + /// + /// @param[in] count + /// The number of uint64_t values to extract. + /// + /// @return + /// \a dst if all values were properly extracted and copied, + /// NULL otherise. + //------------------------------------------------------------------ + void * + GetU64 ( lldb::offset_t *offset_ptr, void *dst, uint32_t count) const; + + //------------------------------------------------------------------ + /// Extract a signed LEB128 value from \a *offset_ptr. + /// + /// Extracts an signed LEB128 number from this object's data + /// starting at the offset pointed to by \a offset_ptr. The offset + /// pointed to by \a offset_ptr will be updated with the offset of + /// the byte following the last extracted byte. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted signed integer value. + //------------------------------------------------------------------ + int64_t + GetSLEB128 (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Extract a unsigned LEB128 value from \a *offset_ptr. + /// + /// Extracts an unsigned LEB128 number from this object's data + /// starting at the offset pointed to by \a offset_ptr. The offset + /// pointed to by \a offset_ptr will be updated with the offset of + /// the byte following the last extracted byte. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + /// The extracted unsigned integer value. + //------------------------------------------------------------------ + uint64_t + GetULEB128 (lldb::offset_t *offset_ptr) const; + + lldb::DataBufferSP & + GetSharedDataBuffer () + { + return m_data_sp; + } + + //------------------------------------------------------------------ + /// Peek at a C string at \a offset. + /// + /// Peeks at a string in the contained data. No verification is done + /// to make sure the entire string lies within the bounds of this + /// object's data, only \a offset is verified to be a valid offset. + /// + /// @param[in] offset + /// An offset into the data. + /// + /// @return + /// A non-NULL C string pointer if \a offset is a valid offset, + /// NULL otherwise. + //------------------------------------------------------------------ + const char * + PeekCStr (lldb::offset_t offset) const; + + //------------------------------------------------------------------ + /// Peek at a bytes at \a offset. + /// + /// Returns a pointer to \a length bytes at \a offset as long as + /// there are \a length bytes available starting at \a offset. + /// + /// @return + /// A non-NULL data pointer if \a offset is a valid offset and + /// there are \a length bytes available at that offset, NULL + /// otherwise. + //------------------------------------------------------------------ + const uint8_t* + PeekData (lldb::offset_t offset, lldb::offset_t length) const + { + if (length > 0 && ValidOffsetForDataOfSize(offset, length)) + return m_start + offset; + return NULL; + } + + //------------------------------------------------------------------ + /// Set the address byte size. + /// + /// Set the size in bytes that will be used when extracting any + /// address and pointer values from data contained in this object. + /// + /// @param[in] addr_size + /// The size in bytes to use when extracting addresses. + //------------------------------------------------------------------ + void + SetAddressByteSize (uint32_t addr_size) + { + m_addr_size = addr_size; + } + + //------------------------------------------------------------------ + /// Set data with a buffer that is caller owned. + /// + /// Use data that is owned by the caller when extracting values. + /// The data must stay around as long as this object, or any object + /// that copies a subset of this object's data, is valid. If \a + /// bytes is NULL, or \a length is zero, this object will contain + /// no data. + /// + /// @param[in] bytes + /// A pointer to caller owned data. + /// + /// @param[in] length + /// The length in bytes of \a bytes. + /// + /// @param[in] byte_order + /// A byte order of the data that we are extracting from. + /// + /// @return + /// The number of bytes that this object now contains. + //------------------------------------------------------------------ + lldb::offset_t + SetData (const void *bytes, lldb::offset_t length, lldb::ByteOrder byte_order); + + //------------------------------------------------------------------ + /// Adopt a subset of \a data. + /// + /// Set this object's data to be a subset of the data bytes in \a + /// data. If \a data contains shared data, then a reference to the + /// shared data will be added to ensure the shared data stays around + /// as long as any objects have references to the shared data. The + /// byte order and the address size settings are copied from \a + /// data. If \a offset is not a valid offset in \a data, then no + /// reference to the shared data will be added. If there are not + /// \a length bytes available in \a data starting at \a offset, + /// the length will be truncated to contains as many bytes as + /// possible. + /// + /// @param[in] data + /// Another DataExtractor object that contains data. + /// + /// @param[in] offset + /// The offset into \a data at which the subset starts. + /// + /// @param[in] length + /// The length in bytes of the subset of \a data. + /// + /// @return + /// The number of bytes that this object now contains. + //------------------------------------------------------------------ + lldb::offset_t + SetData (const DataExtractor& data, lldb::offset_t offset, lldb::offset_t length); + + //------------------------------------------------------------------ + /// Adopt a subset of shared data in \a data_sp. + /// + /// Copies the data shared pointer which adds a reference to the + /// contained in \a data_sp. The shared data reference is reference + /// counted to ensure the data lives as long as anyone still has a + /// valid shared pointer to the data in \a data_sp. The byte order + /// and address byte size settings remain the same. If + /// \a offset is not a valid offset in \a data_sp, then no reference + /// to the shared data will be added. If there are not \a length + /// bytes available in \a data starting at \a offset, the length + /// will be truncated to contains as many bytes as possible. + /// + /// @param[in] data_sp + /// A shared pointer to data. + /// + /// @param[in] offset + /// The offset into \a data_sp at which the subset starts. + /// + /// @param[in] length + /// The length in bytes of the subset of \a data_sp. + /// + /// @return + /// The number of bytes that this object now contains. + //------------------------------------------------------------------ + lldb::offset_t + SetData (const lldb::DataBufferSP& data_sp, lldb::offset_t offset = 0, lldb::offset_t length = LLDB_INVALID_OFFSET); + + //------------------------------------------------------------------ + /// Set the byte_order value. + /// + /// Sets the byte order of the data to extract. Extracted values + /// will be swapped if necessary when decoding. + /// + /// @param[in] byte_order + /// The byte order value to use when extracting data. + //------------------------------------------------------------------ + void + SetByteOrder (lldb::ByteOrder byte_order) + { + m_byte_order = byte_order; + } + + //------------------------------------------------------------------ + /// Skip an LEB128 number at \a *offset_ptr. + /// + /// Skips a LEB128 number (signed or unsigned) from this object's + /// data starting at the offset pointed to by \a offset_ptr. The + /// offset pointed to by \a offset_ptr will be updated with the + /// offset of the byte following the last extracted byte. + /// + /// @param[in,out] offset_ptr + /// A pointer to an offset within the data that will be advanced + /// by the appropriate number of bytes if the value is extracted + /// correctly. If the offset is out of bounds or there are not + /// enough bytes to extract this value, the offset will be left + /// unmodified. + /// + /// @return + // The number of bytes consumed during the extraction. + //------------------------------------------------------------------ + uint32_t + Skip_LEB128 (lldb::offset_t *offset_ptr) const; + + //------------------------------------------------------------------ + /// Test the validity of \a offset. + /// + /// @return + /// \b true if \a offset is a valid offset into the data in this + /// object, \b false otherwise. + //------------------------------------------------------------------ + bool + ValidOffset (lldb::offset_t offset) const + { + return offset < GetByteSize(); + } + + //------------------------------------------------------------------ + /// Test the availability of \a length bytes of data from \a offset. + /// + /// @return + /// \b true if \a offset is a valid offset and there are \a + /// length bytes available at that offset, \b false otherwise. + //------------------------------------------------------------------ + bool + ValidOffsetForDataOfSize (lldb::offset_t offset, lldb::offset_t length) const + { + return length <= BytesLeft (offset); + } + + size_t + Copy (DataExtractor& dest_data) const; + + bool + Append (DataExtractor& rhs); + + bool + Append (void* bytes, lldb::offset_t length); + + lldb::offset_t + BytesLeft (lldb::offset_t offset) const + { + const lldb::offset_t size = GetByteSize(); + if (size > offset) + return size - offset; + return 0; + } + +protected: + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + const uint8_t * m_start; ///< A pointer to the first byte of data. + const uint8_t * m_end; ///< A pointer to the byte that is past the end of the data. + lldb::ByteOrder m_byte_order; ///< The byte order of the data we are extracting from. + uint32_t m_addr_size; ///< The address size to use when extracting pointers or addresses + mutable lldb::DataBufferSP m_data_sp; ///< The shared pointer to data that can be shared among multilple instances +}; + +} // namespace lldb_private + +#endif // #if defined (__cplusplus) +#endif // #ifndef liblldb_DataExtractor_h_ diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h new file mode 100644 index 0000000..bed93fe --- /dev/null +++ b/include/lldb/Core/Debugger.h @@ -0,0 +1,397 @@ +//===-- Debugger.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_Debugger_h_ +#define liblldb_Debugger_h_ +#if defined(__cplusplus) + + +#include <stdint.h> +#include <unistd.h> + +#include <stack> + +#include "lldb/lldb-public.h" + +#include "lldb/API/SBDefines.h" + +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Communication.h" +#include "lldb/Core/InputReaderStack.h" +#include "lldb/Core/Listener.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/SourceManager.h" +#include "lldb/Core/UserID.h" +#include "lldb/Core/UserSettingsController.h" +#include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/Terminal.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/TargetList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Debugger Debugger.h "lldb/Core/Debugger.h" +/// @brief A class to manage flag bits. +/// +/// Provides a global root objects for the debugger core. +//---------------------------------------------------------------------- + + +class Debugger : + public std::enable_shared_from_this<Debugger>, + public UserID, + public Properties, + public BroadcasterManager +{ +friend class SourceManager; // For GetSourceFileCache. + +public: + + static lldb::DebuggerSP + CreateInstance (lldb::LogOutputCallback log_callback = NULL, void *baton = NULL); + + static lldb::TargetSP + FindTargetWithProcessID (lldb::pid_t pid); + + static lldb::TargetSP + FindTargetWithProcess (Process *process); + + static void + Initialize (); + + static void + Terminate (); + + static void + SettingsInitialize (); + + static void + SettingsTerminate (); + + static void + Destroy (lldb::DebuggerSP &debugger_sp); + + virtual + ~Debugger (); + + void Clear(); + + bool + GetAsyncExecution (); + + void + SetAsyncExecution (bool async); + + File & + GetInputFile () + { + return m_input_file.GetFile(); + } + + File & + GetOutputFile () + { + return m_output_file.GetFile(); + } + + File & + GetErrorFile () + { + return m_error_file.GetFile(); + } + + void + SetInputFileHandle (FILE *fh, bool tranfer_ownership); + + void + SetOutputFileHandle (FILE *fh, bool tranfer_ownership); + + void + SetErrorFileHandle (FILE *fh, bool tranfer_ownership); + + void + SaveInputTerminalState(); + + void + RestoreInputTerminalState(); + + Stream& + GetOutputStream () + { + return m_output_file; + } + + Stream& + GetErrorStream () + { + return m_error_file; + } + + lldb::StreamSP + GetAsyncOutputStream (); + + lldb::StreamSP + GetAsyncErrorStream (); + + CommandInterpreter & + GetCommandInterpreter () + { + assert (m_command_interpreter_ap.get()); + return *m_command_interpreter_ap; + } + + Listener & + GetListener () + { + return m_listener; + } + + // This returns the Debugger's scratch source manager. It won't be able to look up files in debug + // information, but it can look up files by absolute path and display them to you. + // To get the target's source manager, call GetSourceManager on the target instead. + SourceManager & + GetSourceManager (); + +public: + + lldb::TargetSP + GetSelectedTarget () + { + return m_target_list.GetSelectedTarget (); + } + + ExecutionContext + GetSelectedExecutionContext(); + //------------------------------------------------------------------ + /// Get accessor for the target list. + /// + /// The target list is part of the global debugger object. This + /// the single debugger shared instance to control where targets + /// get created and to allow for tracking and searching for targets + /// based on certain criteria. + /// + /// @return + /// A global shared target list. + //------------------------------------------------------------------ + TargetList & + GetTargetList () + { + return m_target_list; + } + + PlatformList & + GetPlatformList () + { + return m_platform_list; + } + + void + DispatchInputInterrupt (); + + void + DispatchInputEndOfFile (); + + void + DispatchInput (const char *bytes, size_t bytes_len); + + void + WriteToDefaultReader (const char *bytes, size_t bytes_len); + + void + PushInputReader (const lldb::InputReaderSP& reader_sp); + + bool + PopInputReader (const lldb::InputReaderSP& reader_sp); + + void + NotifyTopInputReader (lldb::InputReaderAction notification); + + bool + InputReaderIsTopReader (const lldb::InputReaderSP& reader_sp); + + static lldb::DebuggerSP + FindDebuggerWithID (lldb::user_id_t id); + + static lldb::DebuggerSP + FindDebuggerWithInstanceName (const ConstString &instance_name); + + static size_t + GetNumDebuggers(); + + static lldb::DebuggerSP + GetDebuggerAtIndex (size_t index); + + static bool + FormatPrompt (const char *format, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, + Stream &s, + ValueObject* valobj = NULL); + + + void + CleanUpInputReaders (); + + static int + TestDebuggerRefCount (); + + bool + GetCloseInputOnEOF () const; + + void + SetCloseInputOnEOF (bool b); + + bool + EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream); + + void + SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton); + + + //---------------------------------------------------------------------- + // Properties Functions + //---------------------------------------------------------------------- + enum StopDisassemblyType + { + eStopDisassemblyTypeNever = 0, + eStopDisassemblyTypeNoSource, + eStopDisassemblyTypeAlways + }; + + virtual Error + SetPropertyValue (const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *property_path, + const char *value); + + bool + GetAutoConfirm () const; + + const char * + GetFrameFormat() const; + + const char * + GetThreadFormat() const; + + lldb::ScriptLanguage + GetScriptLanguage() const; + + bool + SetScriptLanguage (lldb::ScriptLanguage script_lang); + + uint32_t + GetTerminalWidth () const; + + bool + SetTerminalWidth (uint32_t term_width); + + const char * + GetPrompt() const; + + void + SetPrompt(const char *p); + + bool + GetUseExternalEditor () const; + + bool + SetUseExternalEditor (bool use_external_editor_p); + + bool + GetUseColor () const; + + bool + SetUseColor (bool use_color); + + uint32_t + GetStopSourceLineCount (bool before) const; + + StopDisassemblyType + GetStopDisassemblyDisplay () const; + + uint32_t + GetDisassemblyLineCount () const; + + bool + GetNotifyVoid () const; + + + const ConstString & + GetInstanceName() + { + return m_instance_name; + } + + typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger); + + bool + LoadPlugin (const FileSpec& spec, Error& error); + +protected: + + static void + DispatchInputCallback (void *baton, const void *bytes, size_t bytes_len); + + lldb::InputReaderSP + GetCurrentInputReader (); + + void + ActivateInputReader (const lldb::InputReaderSP &reader_sp); + + bool + CheckIfTopInputReaderIsDone (); + + SourceManager::SourceFileCache & + GetSourceFileCache () + { + return m_source_file_cache; + } + Communication m_input_comm; + StreamFile m_input_file; + StreamFile m_output_file; + StreamFile m_error_file; + TerminalState m_terminal_state; + TargetList m_target_list; + PlatformList m_platform_list; + Listener m_listener; + std::unique_ptr<SourceManager> m_source_manager_ap; // This is a scratch source manager that we return if we have no targets. + SourceManager::SourceFileCache m_source_file_cache; // All the source managers for targets created in this debugger used this shared + // source file cache. + std::unique_ptr<CommandInterpreter> m_command_interpreter_ap; + + InputReaderStack m_input_reader_stack; + std::string m_input_reader_data; + typedef std::map<std::string, lldb::StreamWP> LogStreamMap; + LogStreamMap m_log_streams; + lldb::StreamSP m_log_callback_stream_sp; + ConstString m_instance_name; + typedef std::vector<lldb::DynamicLibrarySP> LoadedPluginsList; + LoadedPluginsList m_loaded_plugins; + + void + InstanceInitialize (); + +private: + + // Use Debugger::CreateInstance() to get a shared pointer to a new + // debugger object + Debugger (lldb::LogOutputCallback m_log_callback, void *baton); + + DISALLOW_COPY_AND_ASSIGN (Debugger); + +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Debugger_h_ diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h new file mode 100644 index 0000000..d6e9007 --- /dev/null +++ b/include/lldb/Core/Disassembler.h @@ -0,0 +1,422 @@ +//===-- Disassembler.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_Disassembler_h_ +#define liblldb_Disassembler_h_ + +// C Includes +// C++ Includes +#include <vector> +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/EmulateInstruction.h" +#include "lldb/Core/Opcode.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class Instruction +{ +public: + Instruction (const Address &address, + lldb::AddressClass addr_class = lldb::eAddressClassInvalid); + + virtual + ~Instruction(); + + const Address & + GetAddress () const + { + return m_address; + } + + const char * + GetMnemonic (const ExecutionContext* exe_ctx) + { + CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); + return m_opcode_name.c_str(); + } + const char * + GetOperands (const ExecutionContext* exe_ctx) + { + CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); + return m_mnemonics.c_str(); + } + + const char * + GetComment (const ExecutionContext* exe_ctx) + { + CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); + return m_comment.c_str(); + } + + virtual void + CalculateMnemonicOperandsAndComment (const ExecutionContext* exe_ctx) = 0; + + lldb::AddressClass + GetAddressClass (); + + void + SetAddress (const Address &addr) + { + // Invalidate the address class to lazily discover + // it if we need to. + m_address_class = lldb::eAddressClassInvalid; + m_address = addr; + } + + virtual void + Dump (Stream *s, + uint32_t max_opcode_byte_size, + bool show_address, + bool show_bytes, + const ExecutionContext* exe_ctx); + + virtual bool + DoesBranch () = 0; + + virtual size_t + Decode (const Disassembler &disassembler, + const DataExtractor& data, + lldb::offset_t data_offset) = 0; + + virtual void + SetDescription (const char *) {} // May be overridden in sub-classes that have descriptions. + + lldb::OptionValueSP + ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type); + + lldb::OptionValueSP + ReadDictionary (FILE *in_file, Stream *out_stream); + + bool + DumpEmulation (const ArchSpec &arch); + + virtual bool + TestEmulation (Stream *stream, const char *test_file_name); + + bool + Emulate (const ArchSpec &arch, + uint32_t evaluate_options, + void *baton, + EmulateInstruction::ReadMemoryCallback read_mem_callback, + EmulateInstruction::WriteMemoryCallback write_mem_calback, + EmulateInstruction::ReadRegisterCallback read_reg_callback, + EmulateInstruction::WriteRegisterCallback write_reg_callback); + + const Opcode & + GetOpcode () const + { + return m_opcode; + } + + uint32_t + GetData (DataExtractor &data); + +protected: + Address m_address; // The section offset address of this instruction + // We include an address class in the Instruction class to + // allow the instruction specify the eAddressClassCodeAlternateISA + // (currently used for thumb), and also to specify data (eAddressClassData). + // The usual value will be eAddressClassCode, but often when + // disassembling memory, you might run into data. This can + // help us to disassemble appropriately. +private: + lldb::AddressClass m_address_class; // Use GetAddressClass () accessor function! +protected: + Opcode m_opcode; // The opcode for this instruction + std::string m_opcode_name; + std::string m_mnemonics; + std::string m_comment; + bool m_calculated_strings; + + void + CalculateMnemonicOperandsAndCommentIfNeeded (const ExecutionContext* exe_ctx) + { + if (!m_calculated_strings) + { + m_calculated_strings = true; + CalculateMnemonicOperandsAndComment(exe_ctx); + } + } +}; + + +class InstructionList +{ +public: + InstructionList(); + ~InstructionList(); + + size_t + GetSize() const; + + uint32_t + GetMaxOpcocdeByteSize () const; + + lldb::InstructionSP + GetInstructionAtIndex (size_t idx) const; + + uint32_t + GetIndexOfNextBranchInstruction(uint32_t start) const; + + uint32_t + GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target); + + void + Clear(); + + void + Append (lldb::InstructionSP &inst_sp); + + void + Dump (Stream *s, + bool show_address, + bool show_bytes, + const ExecutionContext* exe_ctx); + +private: + typedef std::vector<lldb::InstructionSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + collection m_instructions; +}; + +class PseudoInstruction : + public Instruction +{ +public: + + PseudoInstruction (); + + virtual + ~PseudoInstruction (); + + virtual bool + DoesBranch (); + + virtual void + CalculateMnemonicOperandsAndComment (const ExecutionContext* exe_ctx) + { + // TODO: fill this in and put opcode name into Instruction::m_opcode_name, + // mnemonic into Instruction::m_mnemonics, and any comment into + // Instruction::m_comment + } + + virtual size_t + Decode (const Disassembler &disassembler, + const DataExtractor &data, + lldb::offset_t data_offset); + + void + SetOpcode (size_t opcode_size, void *opcode_data); + + virtual void + SetDescription (const char *description); + +protected: + std::string m_description; + + DISALLOW_COPY_AND_ASSIGN (PseudoInstruction); +}; + +class Disassembler : + public std::enable_shared_from_this<Disassembler>, + public PluginInterface +{ +public: + + enum + { + eOptionNone = 0u, + eOptionShowBytes = (1u << 0), + eOptionRawOuput = (1u << 1), + eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains the current PC (mixed mode only) + eOptionMarkPCAddress = (1u << 3) // Mark the disassembly line the contains the PC + }; + + enum HexImmediateStyle + { + eHexStyleC, + eHexStyleAsm, + }; + + // FindPlugin should be lax about the flavor string (it is too annoying to have various internal uses of the + // disassembler fail because the global flavor string gets set wrong. Instead, if you get a flavor string you + // don't understand, use the default. Folks who care to check can use the FlavorValidForArchSpec method on the + // disassembler they got back. + static lldb::DisassemblerSP + FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name); + + // This version will use the value in the Target settings if flavor is NULL; + static lldb::DisassemblerSP + FindPluginForTarget(const lldb::TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name); + + static lldb::DisassemblerSP + DisassembleRange (const ArchSpec &arch, + const char *plugin_name, + const char *flavor, + const ExecutionContext &exe_ctx, + const AddressRange &disasm_range); + + static lldb::DisassemblerSP + DisassembleBytes (const ArchSpec &arch, + const char *plugin_name, + const char *flavor, + const Address &start, + const void *bytes, + size_t length, + uint32_t max_num_instructions, + bool data_from_file); + + static bool + Disassemble (Debugger &debugger, + const ArchSpec &arch, + const char *plugin_name, + const char *flavor, + const ExecutionContext &exe_ctx, + const AddressRange &range, + uint32_t num_instructions, + uint32_t num_mixed_context_lines, + uint32_t options, + Stream &strm); + + static bool + Disassemble (Debugger &debugger, + const ArchSpec &arch, + const char *plugin_name, + const char *flavor, + const ExecutionContext &exe_ctx, + const Address &start, + uint32_t num_instructions, + uint32_t num_mixed_context_lines, + uint32_t options, + Stream &strm); + + static size_t + Disassemble (Debugger &debugger, + const ArchSpec &arch, + const char *plugin_name, + const char *flavor, + const ExecutionContext &exe_ctx, + SymbolContextList &sc_list, + uint32_t num_instructions, + uint32_t num_mixed_context_lines, + uint32_t options, + Stream &strm); + + static bool + Disassemble (Debugger &debugger, + const ArchSpec &arch, + const char *plugin_name, + const char *flavor, + const ExecutionContext &exe_ctx, + const ConstString &name, + Module *module, + uint32_t num_instructions, + uint32_t num_mixed_context_lines, + uint32_t options, + Stream &strm); + + static bool + Disassemble (Debugger &debugger, + const ArchSpec &arch, + const char *plugin_name, + const char *flavor, + const ExecutionContext &exe_ctx, + uint32_t num_instructions, + uint32_t num_mixed_context_lines, + uint32_t options, + Stream &strm); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Disassembler(const ArchSpec &arch, const char *flavor); + virtual ~Disassembler(); + + typedef const char * (*SummaryCallback)(const Instruction& inst, ExecutionContext *exe_context, void *user_data); + + static bool + PrintInstructions (Disassembler *disasm_ptr, + Debugger &debugger, + const ArchSpec &arch, + const ExecutionContext &exe_ctx, + uint32_t num_instructions, + uint32_t num_mixed_context_lines, + uint32_t options, + Stream &strm); + + size_t + ParseInstructions (const ExecutionContext *exe_ctx, + const AddressRange &range, + Stream *error_strm_ptr, + bool prefer_file_cache); + + size_t + ParseInstructions (const ExecutionContext *exe_ctx, + const Address &range, + uint32_t num_instructions, + bool prefer_file_cache); + + virtual size_t + DecodeInstructions (const Address &base_addr, + const DataExtractor& data, + lldb::offset_t data_offset, + size_t num_instructions, + bool append, + bool data_from_file) = 0; + + InstructionList & + GetInstructionList (); + + const InstructionList & + GetInstructionList () const; + + const ArchSpec & + GetArchitecture () const + { + return m_arch; + } + + const char * + GetFlavor () const + { + return m_flavor.c_str(); + } + + virtual bool + FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) = 0; + +protected: + //------------------------------------------------------------------ + // Classes that inherit from Disassembler can see and modify these + //------------------------------------------------------------------ + const ArchSpec m_arch; + InstructionList m_instruction_list; + lldb::addr_t m_base_addr; + std::string m_flavor; + +private: + //------------------------------------------------------------------ + // For Disassembler only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (Disassembler); +}; + +} // namespace lldb_private + +#endif // liblldb_Disassembler_h_ diff --git a/include/lldb/Core/EmulateInstruction.h b/include/lldb/Core/EmulateInstruction.h new file mode 100644 index 0000000..08b97e4 --- /dev/null +++ b/include/lldb/Core/EmulateInstruction.h @@ -0,0 +1,641 @@ +//===-- EmulateInstruction.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_EmulateInstruction_h_ +#define lldb_EmulateInstruction_h_ + +#include <string> + +#include "lldb/lldb-private.h" +#include "lldb/lldb-public.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Core/Opcode.h" +#include "lldb/Core/RegisterValue.h" + +//---------------------------------------------------------------------- +/// @class EmulateInstruction EmulateInstruction.h "lldb/Core/EmulateInstruction.h" +/// @brief A class that allows emulation of CPU opcodes. +/// +/// This class is a plug-in interface that is accessed through the +/// standard static FindPlugin function call in the EmulateInstruction +/// class. The FindPlugin takes a target triple and returns a new object +/// if there is a plug-in that supports the architecture and OS. Four +/// callbacks and a baton are provided. The four callbacks are read +/// register, write register, read memory and write memory. +/// +/// This class is currently designed for these main use cases: +/// - Auto generation of Call Frame Information (CFI) from assembly code +/// - Predicting single step breakpoint locations +/// - Emulating instructions for breakpoint traps +/// +/// Objects can be asked to read an instruction which will cause a call +/// to the read register callback to get the PC, followed by a read +/// memory call to read the opcode. If ReadInstruction () returns true, +/// then a call to EmulateInstruction::EvaluateInstruction () can be +/// made. At this point the EmulateInstruction subclass will use all of +/// the callbacks to emulate an instruction. +/// +/// Clients that provide the callbacks can either do the read/write +/// registers/memory to actually emulate the instruction on a real or +/// virtual CPU, or watch for the EmulateInstruction::Context which +/// is context for the read/write register/memory which explains why +/// the callback is being called. Examples of a context are: +/// "pushing register 3 onto the stack at offset -12", or "adjusting +/// stack pointer by -16". This extra context allows the generation of +/// CFI information from assembly code without having to actually do +/// the read/write register/memory. +/// +/// Clients must be prepared that not all instructions for an +/// Instruction Set Architecture (ISA) will be emulated. +/// +/// Subclasses at the very least should implement the instructions that +/// save and restore registers onto the stack and adjustment to the stack +/// pointer. By just implementing a few instructions for an ISA that are +/// the typical prologue opcodes, you can then generate CFI using a +/// class that will soon be available. +/// +/// Implementing all of the instructions that affect the PC can then +/// allow single step prediction support. +/// +/// Implementing all of the instructions allows for emulation of opcodes +/// for breakpoint traps and will pave the way for "thread centric" +/// debugging. The current debugging model is "process centric" where +/// all threads must be stopped when any thread is stopped; when +/// hitting software breakpoints we must disable the breakpoint by +/// restoring the original breakpoint opcde, single stepping and +/// restoring the breakpoint trap. If all threads were allowed to run +/// then other threads could miss the breakpoint. +/// +/// This class centralizes the code that usually is done in separate +/// code paths in a debugger (single step prediction, finding save +/// restore locations of registers for unwinding stack frame variables) +/// and emulating the intruction is just a bonus. +//---------------------------------------------------------------------- + +namespace lldb_private { + +class EmulateInstruction : + public PluginInterface +{ +public: + + static EmulateInstruction* + FindPlugin (const ArchSpec &arch, + InstructionType supported_inst_type, + const char *plugin_name); + + enum ContextType + { + eContextInvalid = 0, + // Read an instruciton opcode from memory + eContextReadOpcode, + + // Usually used for writing a register value whose source value is an + // immediate + eContextImmediate, + + // Exclusively used when saving a register to the stack as part of the + // prologue + eContextPushRegisterOnStack, + + // Exclusively used when restoring a register off the stack as part of + // the epilogue + eContextPopRegisterOffStack, + + // Add or subtract a value from the stack + eContextAdjustStackPointer, + + // Adjust the frame pointer for the current frame + eContextSetFramePointer, + + // Add or subtract a value from a base address register (other than SP) + eContextAdjustBaseRegister, + + // Add or subtract a value from the PC or store a value to the PC. + eContextAdjustPC, + + // Used in WriteRegister callbacks to indicate where the + eContextRegisterPlusOffset, + + // Used in WriteMemory callback to indicate where the data came from + eContextRegisterStore, + + eContextRegisterLoad, + + // Used when performing a PC-relative branch where the + eContextRelativeBranchImmediate, + + // Used when performing an absolute branch where the + eContextAbsoluteBranchRegister, + + // Used when performing a supervisor call to an operating system to + // provide a service: + eContextSupervisorCall, + + // Used when performing a MemU operation to read the PC-relative offset + // from an address. + eContextTableBranchReadMemory, + + // Used when random bits are written into a register + eContextWriteRegisterRandomBits, + + // Used when random bits are written to memory + eContextWriteMemoryRandomBits, + + eContextArithmetic, + + eContextAdvancePC, + + eContextReturnFromException + }; + + enum InfoType { + eInfoTypeRegisterPlusOffset, + eInfoTypeRegisterPlusIndirectOffset, + eInfoTypeRegisterToRegisterPlusOffset, + eInfoTypeRegisterToRegisterPlusIndirectOffset, + eInfoTypeRegisterRegisterOperands, + eInfoTypeOffset, + eInfoTypeRegister, + eInfoTypeImmediate, + eInfoTypeImmediateSigned, + eInfoTypeAddress, + eInfoTypeISAAndImmediate, + eInfoTypeISAAndImmediateSigned, + eInfoTypeISA, + eInfoTypeNoArgs + } InfoType; + + struct Context + { + ContextType type; + enum InfoType info_type; + union + { + struct RegisterPlusOffset + { + RegisterInfo reg; // base register + int64_t signed_offset; // signed offset added to base register + } RegisterPlusOffset; + + struct RegisterPlusIndirectOffset + { + RegisterInfo base_reg; // base register number + RegisterInfo offset_reg; // offset register kind + } RegisterPlusIndirectOffset; + + struct RegisterToRegisterPlusOffset + { + RegisterInfo data_reg; // source/target register for data + RegisterInfo base_reg; // base register for address calculation + int64_t offset; // offset for address calculation + } RegisterToRegisterPlusOffset; + + struct RegisterToRegisterPlusIndirectOffset + { + RegisterInfo base_reg; // base register for address calculation + RegisterInfo offset_reg; // offset register for address calculation + RegisterInfo data_reg; // source/target register for data + } RegisterToRegisterPlusIndirectOffset; + + struct RegisterRegisterOperands + { + RegisterInfo operand1; // register containing first operand for binary op + RegisterInfo operand2; // register containing second operand for binary op + } RegisterRegisterOperands; + + int64_t signed_offset; // signed offset by which to adjust self (for registers only) + + RegisterInfo reg; // plain register + + uint64_t unsigned_immediate;// unsigned immediate value + int64_t signed_immediate; // signed immediate value + + lldb::addr_t address; // direct address + + struct ISAAndImmediate + { + uint32_t isa; + uint32_t unsigned_data32; // immdiate data + } ISAAndImmediate; + + struct ISAAndImmediateSigned + { + uint32_t isa; + int32_t signed_data32; // signed immdiate data + } ISAAndImmediateSigned; + + uint32_t isa; + + } info; + + Context () : + type (eContextInvalid), + info_type (eInfoTypeNoArgs) + { + } + + void + SetRegisterPlusOffset (RegisterInfo base_reg, + int64_t signed_offset) + { + info_type = eInfoTypeRegisterPlusOffset; + info.RegisterPlusOffset.reg = base_reg; + info.RegisterPlusOffset.signed_offset = signed_offset; + } + + void + SetRegisterPlusIndirectOffset (RegisterInfo base_reg, + RegisterInfo offset_reg) + { + info_type = eInfoTypeRegisterPlusIndirectOffset; + info.RegisterPlusIndirectOffset.base_reg = base_reg; + info.RegisterPlusIndirectOffset.offset_reg = offset_reg; + } + + void + SetRegisterToRegisterPlusOffset (RegisterInfo data_reg, + RegisterInfo base_reg, + int64_t offset) + { + info_type = eInfoTypeRegisterToRegisterPlusOffset; + info.RegisterToRegisterPlusOffset.data_reg = data_reg; + info.RegisterToRegisterPlusOffset.base_reg = base_reg; + info.RegisterToRegisterPlusOffset.offset = offset; + } + + void + SetRegisterToRegisterPlusIndirectOffset (RegisterInfo base_reg, + RegisterInfo offset_reg, + RegisterInfo data_reg) + { + info_type = eInfoTypeRegisterToRegisterPlusIndirectOffset; + info.RegisterToRegisterPlusIndirectOffset.base_reg = base_reg; + info.RegisterToRegisterPlusIndirectOffset.offset_reg = offset_reg; + info.RegisterToRegisterPlusIndirectOffset.data_reg = data_reg; + } + + void + SetRegisterRegisterOperands (RegisterInfo op1_reg, + RegisterInfo op2_reg) + { + info_type = eInfoTypeRegisterRegisterOperands; + info.RegisterRegisterOperands.operand1 = op1_reg; + info.RegisterRegisterOperands.operand2 = op2_reg; + } + + void + SetOffset (int64_t signed_offset) + { + info_type = eInfoTypeOffset; + info.signed_offset = signed_offset; + } + + void + SetRegister (RegisterInfo reg) + { + info_type = eInfoTypeRegister; + info.reg = reg; + } + + void + SetImmediate (uint64_t immediate) + { + info_type = eInfoTypeImmediate; + info.unsigned_immediate = immediate; + } + + void + SetImmediateSigned (int64_t signed_immediate) + { + info_type = eInfoTypeImmediateSigned; + info.signed_immediate = signed_immediate; + } + + void + SetAddress (lldb::addr_t address) + { + info_type = eInfoTypeAddress; + info.address = address; + } + void + SetISAAndImmediate (uint32_t isa, uint32_t data) + { + info_type = eInfoTypeISAAndImmediate; + info.ISAAndImmediate.isa = isa; + info.ISAAndImmediate.unsigned_data32 = data; + } + + void + SetISAAndImmediateSigned (uint32_t isa, int32_t data) + { + info_type = eInfoTypeISAAndImmediateSigned; + info.ISAAndImmediateSigned.isa = isa; + info.ISAAndImmediateSigned.signed_data32 = data; + } + + void + SetISA (uint32_t isa) + { + info_type = eInfoTypeISA; + info.isa = isa; + } + + void + SetNoArgs () + { + info_type = eInfoTypeNoArgs; + } + + void + Dump (Stream &s, + EmulateInstruction *instruction) const; + + }; + + typedef size_t (*ReadMemoryCallback) (EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, + void *dst, + size_t length); + + typedef size_t (*WriteMemoryCallback) (EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, + const void *dst, + size_t length); + + typedef bool (*ReadRegisterCallback) (EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + typedef bool (*WriteRegisterCallback) (EmulateInstruction *instruction, + void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + EmulateInstruction (const ArchSpec &arch); + + virtual ~EmulateInstruction() + { + } + //---------------------------------------------------------------------- + // Mandatory overrides + //---------------------------------------------------------------------- + virtual bool + SupportsEmulatingIntructionsOfType (InstructionType inst_type) = 0; + + virtual bool + SetTargetTriple (const ArchSpec &arch) = 0; + + virtual bool + ReadInstruction () = 0; + + virtual bool + EvaluateInstruction (uint32_t evaluate_options) = 0; + + virtual bool + TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0; + + virtual bool + GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo ®_info) = 0; + + //---------------------------------------------------------------------- + // Optional overrides + //---------------------------------------------------------------------- + virtual bool + SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target); + + virtual bool + CreateFunctionEntryUnwind (UnwindPlan &unwind_plan); + + static const char * + TranslateRegister (uint32_t reg_kind, uint32_t reg_num, std::string ®_name); + + //---------------------------------------------------------------------- + // RegisterInfo variants + //---------------------------------------------------------------------- + bool + ReadRegister (const RegisterInfo *reg_info, + RegisterValue& reg_value); + + uint64_t + ReadRegisterUnsigned (const RegisterInfo *reg_info, + uint64_t fail_value, + bool *success_ptr); + + bool + WriteRegister (const Context &context, + const RegisterInfo *ref_info, + const RegisterValue& reg_value); + + bool + WriteRegisterUnsigned (const Context &context, + const RegisterInfo *reg_info, + uint64_t reg_value); + + //---------------------------------------------------------------------- + // Register kind and number variants + //---------------------------------------------------------------------- + bool + ReadRegister (uint32_t reg_kind, + uint32_t reg_num, + RegisterValue& reg_value); + + bool + WriteRegister (const Context &context, + uint32_t reg_kind, + uint32_t reg_num, + const RegisterValue& reg_value); + + uint64_t + ReadRegisterUnsigned (uint32_t reg_kind, + uint32_t reg_num, + uint64_t fail_value, + bool *success_ptr); + + bool + WriteRegisterUnsigned (const Context &context, + uint32_t reg_kind, + uint32_t reg_num, + uint64_t reg_value); + + + size_t + ReadMemory (const Context &context, + lldb::addr_t addr, + void *dst, + size_t dst_len); + + uint64_t + ReadMemoryUnsigned (const Context &context, + lldb::addr_t addr, + size_t byte_size, + uint64_t fail_value, + bool *success_ptr); + + bool + WriteMemory (const Context &context, + lldb::addr_t addr, + const void *src, + size_t src_len); + + bool + WriteMemoryUnsigned (const Context &context, + lldb::addr_t addr, + uint64_t uval, + size_t uval_byte_size); + + uint32_t + GetAddressByteSize () const + { + return m_arch.GetAddressByteSize(); + } + + lldb::ByteOrder + GetByteOrder () const + { + return m_arch.GetByteOrder(); + } + + const Opcode & + GetOpcode () const + { + return m_opcode; + } + + lldb::addr_t + GetAddress () const + { + return m_addr; + } + + const ArchSpec & + GetArchitecture () const + { + return m_arch; + } + + + static size_t + ReadMemoryFrame (EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, + void *dst, + size_t length); + + static size_t + WriteMemoryFrame (EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, + const void *dst, + size_t length); + + static bool + ReadRegisterFrame (EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + + static bool + WriteRegisterFrame (EmulateInstruction *instruction, + void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + static size_t + ReadMemoryDefault (EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, + void *dst, + size_t length); + + static size_t + WriteMemoryDefault (EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, + const void *dst, + size_t length); + + static bool + ReadRegisterDefault (EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + + static bool + WriteRegisterDefault (EmulateInstruction *instruction, + void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + void + SetBaton (void *baton); + + void + SetCallbacks (ReadMemoryCallback read_mem_callback, + WriteMemoryCallback write_mem_callback, + ReadRegisterCallback read_reg_callback, + WriteRegisterCallback write_reg_callback); + + void + SetReadMemCallback (ReadMemoryCallback read_mem_callback); + + void + SetWriteMemCallback (WriteMemoryCallback write_mem_callback); + + void + SetReadRegCallback (ReadRegisterCallback read_reg_callback); + + void + SetWriteRegCallback (WriteRegisterCallback write_reg_callback); + + static bool + GetBestRegisterKindAndNumber (const RegisterInfo *reg_info, + uint32_t ®_kind, + uint32_t ®_num); + + static uint32_t + GetInternalRegisterNumber (RegisterContext *reg_ctx, + const RegisterInfo ®_info); + +protected: + ArchSpec m_arch; + void * m_baton; + ReadMemoryCallback m_read_mem_callback; + WriteMemoryCallback m_write_mem_callback; + ReadRegisterCallback m_read_reg_callback; + WriteRegisterCallback m_write_reg_callback; + lldb::addr_t m_addr; + Opcode m_opcode; + + +private: + //------------------------------------------------------------------ + // For EmulateInstruction only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (EmulateInstruction); +}; + +} // namespace lldb_private + +#endif // lldb_EmulateInstruction_h_ diff --git a/include/lldb/Core/Error.h b/include/lldb/Core/Error.h new file mode 100644 index 0000000..9e45d5f --- /dev/null +++ b/include/lldb/Core/Error.h @@ -0,0 +1,312 @@ +//===-- Error.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef __DCError_h__ +#define __DCError_h__ +#if defined(__cplusplus) + +#if defined (__APPLE__) +#include <mach/mach.h> +#endif +#include <stdint.h> +#include <stdio.h> +#include <string> + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class Log; + +//---------------------------------------------------------------------- +/// @class Error Error.h "lldb/Core/Error.h" +/// @brief An error handling class. +/// +/// This class is designed to be able to hold any error code that can be +/// encountered on a given platform. The errors are stored as a value +/// of type Error::ValueType. This value should be large enough to hold +/// any and all errors that the class supports. Each error has an +/// associated type that is of type lldb::ErrorType. New types +/// can be added to support new error types, and architecture specific +/// types can be enabled. In the future we may wish to switch to a +/// registration mechanism where new error types can be registered at +/// runtime instead of a hard coded scheme. +/// +/// All errors in this class also know how to generate a string +/// representation of themselves for printing results and error codes. +/// The string value will be fetched on demand and its string value will +/// be cached until the error is cleared of the value of the error +/// changes. +//---------------------------------------------------------------------- +class Error +{ +public: + //------------------------------------------------------------------ + /// Every error value that this object can contain needs to be able + /// to fit into ValueType. + //------------------------------------------------------------------ + typedef uint32_t ValueType; + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize the error object with a generic success value. + /// + /// @param[in] err + /// An error code. + /// + /// @param[in] type + /// The type for \a err. + //------------------------------------------------------------------ + Error (); + + explicit + Error (ValueType err, lldb::ErrorType type = lldb::eErrorTypeGeneric); + + explicit + Error (const char* err_str); + + Error (const Error &rhs); + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// @param[in] err + /// An error code. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const Error& + operator = (const Error& rhs); + + + //------------------------------------------------------------------ + /// Assignment operator from a kern_return_t. + /// + /// Sets the type to \c MachKernel and the error code to \a err. + /// + /// @param[in] err + /// A mach error code. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const Error& + operator = (uint32_t err); + + ~Error(); + + //------------------------------------------------------------------ + /// Get the error string associated with the current error. + // + /// Gets the error value as a NULL terminated C string. The error + /// string will be fetched and cached on demand. The error string + /// will be retrieved from a callback that is appropriate for the + /// type of the error and will be cached until the error value is + /// changed or cleared. + /// + /// @return + /// The error as a NULL terminated C string value if the error + /// is valid and is able to be converted to a string value, + /// NULL otherwise. + //------------------------------------------------------------------ + const char * + AsCString (const char *default_error_str = "unknown error") const; + + //------------------------------------------------------------------ + /// Clear the object state. + /// + /// Reverts the state of this object to contain a generic success + /// value and frees any cached error string value. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Test for error condition. + /// + /// @return + /// \b true if this object contains an error, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + Fail () const; + + //------------------------------------------------------------------ + /// Access the error value. + /// + /// @return + /// The error value. + //------------------------------------------------------------------ + ValueType + GetError () const; + + //------------------------------------------------------------------ + /// Access the error type. + /// + /// @return + /// The error type enumeration value. + //------------------------------------------------------------------ + lldb::ErrorType + GetType () const; + + //------------------------------------------------------------------ + /// Log an error to Log(). + /// + /// Log the error given a formatted string \a format. If the this + /// object contains an error code, update the error string to + /// contain the prefix "error: ", followed by the formatted string, + /// followed by the error value and any string that describes the + /// error value. This allows more context to be given to an error + /// string that remains cached in this object. Logging always occurs + /// even when the error code contains a non-error value. + /// + /// @param[in] format + /// A printf style format string. + /// + /// @param[in] ... + /// Variable arguments that are needed for the printf style + /// format string \a format. + //------------------------------------------------------------------ + void + PutToLog (Log *log, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + + //------------------------------------------------------------------ + /// Log an error to Log() if the error value is an error. + /// + /// Log the error given a formatted string \a format only if the + /// error value in this object describes an error condition. If the + /// this object contains an error, update the error string to + /// contain the prefix "error: " followed by the formatted string, + /// followed by the error value and any string that describes the + /// error value. This allows more context to be given to an error + /// string that remains cached in this object. + /// + /// @param[in] format + /// A printf style format string. + /// + /// @param[in] ... + /// Variable arguments that are needed for the printf style + /// format string \a format. + //------------------------------------------------------------------ + void + LogIfError (Log *log, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + + //------------------------------------------------------------------ + /// Set accessor from a kern_return_t. + /// + /// Set accesssor for the error value to \a err and the error type + /// to \c MachKernel. + /// + /// @param[in] err + /// A mach error code. + //------------------------------------------------------------------ + void + SetMachError (uint32_t err); + + //------------------------------------------------------------------ + /// Set accesssor with an error value and type. + /// + /// Set accesssor for the error value to \a err and the error type + /// to \a type. + /// + /// @param[in] err + /// A mach error code. + /// + /// @param[in] type + /// The type for \a err. + //------------------------------------------------------------------ + void + SetError (ValueType err, lldb::ErrorType type); + + //------------------------------------------------------------------ + /// Set the current error to errno. + /// + /// Update the error value to be \c errno and update the type to + /// be \c Error::POSIX. + //------------------------------------------------------------------ + void + SetErrorToErrno (); + + //------------------------------------------------------------------ + /// Set the current error to a generic error. + /// + /// Update the error value to be \c LLDB_GENERIC_ERROR and update the + /// type to be \c Error::Generic. + //------------------------------------------------------------------ + void + SetErrorToGenericError (); + + //------------------------------------------------------------------ + /// Set the current error string to \a err_str. + /// + /// Set accessor for the error string value for a generic errors, + /// or to supply additional details above and beyond the standard + /// error strings that the standard type callbacks typically + /// provide. This allows custom strings to be supplied as an + /// error explanation. The error string value will remain until the + /// error value is cleared or a new error value/type is assigned. + /// + /// @param err_str + /// The new custom error string to copy and cache. + //------------------------------------------------------------------ + void + SetErrorString (const char *err_str); + + //------------------------------------------------------------------ + /// Set the current error string to a formatted error string. + /// + /// @param format + /// A printf style format string + //------------------------------------------------------------------ + int + SetErrorStringWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + int + SetErrorStringWithVarArg (const char *format, va_list args); + + //------------------------------------------------------------------ + /// Test for success condition. + /// + /// Returns true if the error code in this object is considered a + /// successful return value. + /// + /// @return + /// \b true if this object contains an value that describes + /// success (non-erro), \b false otherwise. + //------------------------------------------------------------------ + bool + Success () const; + + //------------------------------------------------------------------ + /// Test for a failure due to a generic interrupt. + /// + /// Returns true if the error code in this object was caused by an interrupt. + /// At present only supports Posix EINTR. + /// + /// @return + /// \b true if this object contains an value that describes + /// failure due to interrupt, \b false otherwise. + //------------------------------------------------------------------ + bool + WasInterrupted() const; + +protected: + //------------------------------------------------------------------ + /// Member variables + //------------------------------------------------------------------ + ValueType m_code; ///< Error code as an integer value. + lldb::ErrorType m_type; ///< The type of the above error code. + mutable std::string m_string; ///< A string representation of the error code. +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // #ifndef __DCError_h__ diff --git a/include/lldb/Core/Event.h b/include/lldb/Core/Event.h new file mode 100644 index 0000000..1c3eec0 --- /dev/null +++ b/include/lldb/Core/Event.h @@ -0,0 +1,217 @@ +//===-- Event.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_Event_h_ +#define liblldb_Event_h_ + +// C Includes +// C++ Includes +#include <list> +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Host/Predicate.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// lldb::EventData +//---------------------------------------------------------------------- +class EventData +{ + friend class Event; + +public: + EventData (); + + virtual + ~EventData(); + + virtual const ConstString & + GetFlavor () const = 0; + + virtual void + Dump (Stream *s) const; + +private: + virtual void + DoOnRemoval (Event *event_ptr) + { + } + + DISALLOW_COPY_AND_ASSIGN (EventData); + +}; + +//---------------------------------------------------------------------- +// lldb::EventDataBytes +//---------------------------------------------------------------------- +class EventDataBytes : public EventData +{ +public: + //------------------------------------------------------------------ + // Constructors + //------------------------------------------------------------------ + EventDataBytes (); + + EventDataBytes (const char *cstr); + + EventDataBytes (const void *src, size_t src_len); + + virtual + ~EventDataBytes(); + + //------------------------------------------------------------------ + // Member functions + //------------------------------------------------------------------ + virtual const ConstString & + GetFlavor () const; + + virtual void + Dump (Stream *s) const; + + const void * + GetBytes() const; + + size_t + GetByteSize() const; + + void + SetBytes (const void *src, size_t src_len); + + void + SwapBytes (std::string &new_bytes); + + void + SetBytesFromCString (const char *cstr); + + //------------------------------------------------------------------ + // Static functions + //------------------------------------------------------------------ + static const EventDataBytes * + GetEventDataFromEvent (const Event *event_ptr); + + static const void * + GetBytesFromEvent (const Event *event_ptr); + + static size_t + GetByteSizeFromEvent (const Event *event_ptr); + + static const ConstString & + GetFlavorString (); + +private: + std::string m_bytes; + + DISALLOW_COPY_AND_ASSIGN (EventDataBytes); + +}; + +//---------------------------------------------------------------------- +// lldb::Event +//---------------------------------------------------------------------- +class Event +{ + friend class Broadcaster; + friend class Listener; + friend class EventData; + +public: + + Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data = NULL); + + Event (uint32_t event_type, EventData *data = NULL); + + ~Event (); + + void + Dump (Stream *s) const; + + EventData * + GetData () + { + return m_data_ap.get(); + } + + const EventData * + GetData () const + { + return m_data_ap.get(); + } + + void + SetData (EventData *new_data) + { + m_data_ap.reset (new_data); + } + + uint32_t + GetType () const + { + return m_type; + } + + void + SetType (uint32_t new_type) + { + m_type = new_type; + } + + Broadcaster * + GetBroadcaster () const + { + return m_broadcaster; + } + + bool + BroadcasterIs (Broadcaster *broadcaster) + { + return broadcaster == m_broadcaster; + } + + void + Clear() + { + m_data_ap.reset(); + } + + +private: + // This is only called by Listener when it pops an event off the queue for + // the listener. It calls the Event Data's DoOnRemoval() method, which is + // virtual and can be overridden by the specific data classes. + + void + DoOnRemoval (); + + // Called by Broadcaster::BroadcastEvent prior to letting all the listeners + // know about it update the contained broadcaster so that events can be + // popped off one queue and re-broadcast to others. + void + SetBroadcaster (Broadcaster *broadcaster) + { + m_broadcaster = broadcaster; + } + + + Broadcaster * m_broadcaster; // The broadcaster that sent this event + uint32_t m_type; // The bit describing this event + std::unique_ptr<EventData> m_data_ap; // User specific data for this event + + + DISALLOW_COPY_AND_ASSIGN (Event); + Event(); // Disallow default constructor +}; + +} // namespace lldb_private + +#endif // liblldb_Event_h_ diff --git a/include/lldb/Core/FileLineResolver.h b/include/lldb/Core/FileLineResolver.h new file mode 100644 index 0000000..e1928f1 --- /dev/null +++ b/include/lldb/Core/FileLineResolver.h @@ -0,0 +1,81 @@ +//===-- FileLineResolver.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_FileLineResolver_h_ +#define liblldb_FileLineResolver_h_ + +// Project includes +#include "lldb/Core/AddressResolver.h" +#include "lldb/Symbol/SymbolContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class FileLineResolver FileLineResolver.h "lldb/Core/FileLineResolver.h" +/// @brief This class finds address for source file and line. Optionally, it will look for inlined +/// instances of the file and line specification. +//---------------------------------------------------------------------- + +class FileLineResolver : + public Searcher +{ +public: + FileLineResolver () : + m_file_spec(), + m_line_number(UINT32_MAX), // Set this to zero for all lines in a file + m_sc_list (), + m_inlines (true) + { + } + + FileLineResolver (const FileSpec &resolver, + uint32_t line_no, + bool check_inlines); + + virtual + ~FileLineResolver (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + + const SymbolContextList & + GetFileLineMatches() + { + return m_sc_list; + } + + void + Clear(); + + void + Reset (const FileSpec &file_spec, + uint32_t line, + bool check_inlines); +protected: + FileSpec m_file_spec; // This is the file spec we are looking for. + uint32_t m_line_number; // This is the line number that we are looking for. + SymbolContextList m_sc_list; + bool m_inlines; // This determines whether the resolver looks for inlined functions or not. + +private: + DISALLOW_COPY_AND_ASSIGN(FileLineResolver); +}; + +} // namespace lldb_private + +#endif // liblldb_FileLineResolver_h_ diff --git a/include/lldb/Core/FileSpecList.h b/include/lldb/Core/FileSpecList.h new file mode 100644 index 0000000..f94bdae --- /dev/null +++ b/include/lldb/Core/FileSpecList.h @@ -0,0 +1,243 @@ +//===-- FileSpecList.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_FileSpecList_h_ +#define liblldb_FileSpecList_h_ +#if defined(__cplusplus) + +#include "lldb/lldb-private.h" +#include "lldb/Host/FileSpec.h" +#include <vector> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class FileSpecList FileSpecList.h "lldb/Core/FileSpecList.h" +/// @brief A file collection class. +/// +/// A class that contains a mutable list of FileSpec objects. +//---------------------------------------------------------------------- +class FileSpecList +{ +public: + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize this object with an empty file list. + //------------------------------------------------------------------ + FileSpecList (); + + //------------------------------------------------------------------ + /// Copy constructor. + /// + /// Initialize this object with a copy of the file list from \a rhs. + /// + /// @param[in] rhs + /// A const reference to another file list object. + //------------------------------------------------------------------ + FileSpecList (const FileSpecList &rhs); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~FileSpecList (); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// Replace the file list in this object with the file list from + /// \a rhs. + /// + /// @param[in] rhs + /// A file list object to copy. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const FileSpecList& + operator= (const FileSpecList &rhs); + + //------------------------------------------------------------------ + /// Append a FileSpec object to the list. + /// + /// Appends \a file to the end of the file list. + /// + /// @param[in] file + /// A new file to append to this file list. + //------------------------------------------------------------------ + void + Append (const FileSpec &file); + + //------------------------------------------------------------------ + /// Append a FileSpec object if unique. + /// + /// Appends \a file to the end of the file list if it doesn't + /// already exist in the file list. + /// + /// @param[in] file + /// A new file to append to this file list. + /// + /// @return + /// \b true if the file was appended, \b false otherwise. + //------------------------------------------------------------------ + bool + AppendIfUnique (const FileSpec &file); + + //------------------------------------------------------------------ + /// Clears the file list. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Dumps the file list to the supplied stream pointer "s". + /// + /// @param[in] s + /// The stream that will be used to dump the object description. + //------------------------------------------------------------------ + void + Dump (Stream *s, const char *separator_cstr = "\n") const; + + //------------------------------------------------------------------ + /// Find a file index. + /// + /// Find the index of the file in the file spec list that matches + /// \a file starting \a idx entries into the file spec list. + /// + /// @param[in] idx + /// An index into the file list. + /// + /// @param[in] file + /// The file specification to search for. + /// + /// @param[in] full + /// Should FileSpec::Equal be called with "full" true or false. + /// + /// @return + /// The index of the file that matches \a file if it is found, + /// else UINT32_MAX is returned. + //------------------------------------------------------------------ + size_t + FindFileIndex (size_t idx, const FileSpec &file, bool full) const; + + //------------------------------------------------------------------ + /// Get file at index. + /// + /// Gets a file from the file list. If \a idx is not a valid index, + /// an empty FileSpec object will be returned. The file objects + /// that are returned can be tested using + /// FileSpec::operator void*(). + /// + /// @param[in] idx + /// An index into the file list. + /// + /// @return + /// A copy of the FileSpec object at index \a idx. If \a idx + /// is out of range, then an empty FileSpec object will be + /// returned. + //------------------------------------------------------------------ + const FileSpec & + GetFileSpecAtIndex (size_t idx) const; + + //------------------------------------------------------------------ + /// Get file specification pointer at index. + /// + /// Gets a file from the file list. The file objects that are + /// returned can be tested using FileSpec::operator void*(). + /// + /// @param[in] idx + /// An index into the file list. + /// + /// @return + /// A pointer to a contained FileSpec object at index \a idx. + /// If \a idx is out of range, then an NULL is returned. + //------------------------------------------------------------------ + const FileSpec * + GetFileSpecPointerAtIndex (size_t idx) const; + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// Return the size in bytes that this object takes in memory. This + /// returns the size in bytes of this object, not any shared string + /// values it may refer to. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + size_t + MemorySize () const; + + bool + IsEmpty() const + { + return m_files.empty(); + } + + //------------------------------------------------------------------ + /// Get the number of files in the file list. + /// + /// @return + /// The number of files in the file spec list. + //------------------------------------------------------------------ + size_t + GetSize () const; + + bool + Insert (size_t idx, const FileSpec &file) + { + if (idx < m_files.size()) + { + m_files.insert(m_files.begin() + idx, file); + return true; + } + else if (idx == m_files.size()) + { + m_files.push_back(file); + return true; + } + return false; + } + + bool + Replace (size_t idx, const FileSpec &file) + { + if (idx < m_files.size()) + { + m_files[idx] = file; + return true; + } + return false; + } + + bool + Remove (size_t idx) + { + if (idx < m_files.size()) + { + m_files.erase(m_files.begin() + idx); + return true; + } + return false; + } + + static size_t GetFilesMatchingPartialPath (const char *path, bool dir_okay, FileSpecList &matches); + +protected: + typedef std::vector<FileSpec> collection; ///< The collection type for the file list. + collection m_files; ///< A collection of FileSpec objects. +}; + +} // namespace lldb_private + + +#endif // #if defined(__cplusplus) +#endif // liblldb_FileSpecList_h_ diff --git a/include/lldb/Core/Flags.h b/include/lldb/Core/Flags.h new file mode 100644 index 0000000..233f098 --- /dev/null +++ b/include/lldb/Core/Flags.h @@ -0,0 +1,253 @@ +//===-- Flags.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_Flags_h_ +#define liblldb_Flags_h_ +#if defined(__cplusplus) + + +#include <stdint.h> +#include <unistd.h> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Flags Flags.h "lldb/Core/Flags.h" +/// @brief A class to manage flags. +/// +/// The Flags class managed flag bits and allows testing and +/// modification of individual or multiple flag bits. +//---------------------------------------------------------------------- +class Flags +{ +public: + //---------------------------------------------------------------------- + /// The value type for flags is a 32 bit unsigned integer type. + //---------------------------------------------------------------------- + typedef uint32_t ValueType; + + //---------------------------------------------------------------------- + /// Construct with initial flag bit values. + /// + /// Constructs this object with \a mask as the initial value for all + /// of the flags. + /// + /// @param[in] mask + /// The initial value for all flags. + //---------------------------------------------------------------------- + Flags (ValueType flags = 0) : + m_flags (flags) + { + } + + //---------------------------------------------------------------------- + /// Copy constructor. + /// + /// Construct and copy the flags from \a rhs. + /// + /// @param[in] rhs + /// A const Flags object reference to copy. + //---------------------------------------------------------------------- + Flags (const Flags& rhs) : + m_flags(rhs.m_flags) + { + } + + //---------------------------------------------------------------------- + /// Destructor. + //---------------------------------------------------------------------- + ~Flags () + { + } + + //---------------------------------------------------------------------- + /// Get accessor for all flags. + /// + /// @return + /// Returns all of the flags as a Flags::ValueType. + //---------------------------------------------------------------------- + ValueType + Get () const + { + return m_flags; + } + + //---------------------------------------------------------------------- + /// Return the number of flags that can be represented in this + /// object. + /// + /// @return + /// The maximum number bits in this flag object. + //---------------------------------------------------------------------- + size_t + GetBitSize() const + { + return sizeof (ValueType) * 8; + } + + //---------------------------------------------------------------------- + /// Set accessor for all flags. + /// + /// @param[in] flags + /// The bits with which to replace all of the current flags. + //---------------------------------------------------------------------- + void + Reset (ValueType flags) + { + m_flags = flags; + } + + //---------------------------------------------------------------------- + /// Clear one or more flags. + /// + /// @param[in] mask + /// A bitfield containing one or more flags. + /// + /// @return + /// The new flags after clearing all bits from \a mask. + //---------------------------------------------------------------------- + ValueType + Clear (ValueType mask = ~(ValueType)0) + { + m_flags &= ~mask; + return m_flags; + } + + + //---------------------------------------------------------------------- + /// Set one or more flags by logical OR'ing \a mask with the current + /// flags. + /// + /// @param[in] mask + /// A bitfield containing one or more flags. + /// + /// @return + /// The new flags after setting all bits from \a mask. + //---------------------------------------------------------------------- + ValueType + Set (ValueType mask) + { + m_flags |= mask; + return m_flags; + } + + + //---------------------------------------------------------------------- + /// Test if all bits in \a mask are 1 in the current flags + /// + /// @return + /// \b true if all flags in \a mask are 1, \b false + /// otherwise. + //---------------------------------------------------------------------- + bool + AllSet (ValueType mask) const + { + return (m_flags & mask) == mask; + } + + //---------------------------------------------------------------------- + /// Test one or more flags. + /// + /// @return + /// \b true if any flags in \a mask are 1, \b false + /// otherwise. + //---------------------------------------------------------------------- + bool + AnySet (ValueType mask) const + { + return (m_flags & mask) != 0; + } + + //---------------------------------------------------------------------- + /// Test a single flag bit. + /// + /// @return + /// \b true if \a bit is set, \b false otherwise. + //---------------------------------------------------------------------- + bool + Test (ValueType bit) const + { + return (m_flags & bit) != 0; + } + + //---------------------------------------------------------------------- + /// Test if all bits in \a mask are clear. + /// + /// @return + /// \b true if \b all flags in \a mask are clear, \b false + /// otherwise. + //---------------------------------------------------------------------- + bool + AllClear (ValueType mask) const + { + return (m_flags & mask) == 0; + } + + bool + AnyClear (ValueType mask) const + { + return (m_flags & mask) != mask; + } + + //---------------------------------------------------------------------- + /// Test a single flag bit to see if it is clear (zero). + /// + /// @return + /// \b true if \a bit is 0, \b false otherwise. + //---------------------------------------------------------------------- + bool + IsClear (ValueType bit) const + { + return (m_flags & bit) == 0; + } + + //---------------------------------------------------------------------- + /// Get the number of zero bits in \a m_flags. + /// + /// @return + /// The number of bits that are set to 0 in the current flags. + //---------------------------------------------------------------------- + size_t + ClearCount () const + { + size_t count = 0; + for (ValueType shift = 0; shift < sizeof(ValueType)*8; ++shift) + { + if ((m_flags & (1u << shift)) == 0) + ++count; + } + return count; + } + + //---------------------------------------------------------------------- + /// Get the number of one bits in \a m_flags. + /// + /// @return + /// The number of bits that are set to 1 in the current flags. + //---------------------------------------------------------------------- + size_t + SetCount () const + { + size_t count = 0; + for (ValueType mask = m_flags; mask; mask >>= 1) + { + if (mask & 1u) + ++count; + } + return count; + } + +protected: + ValueType m_flags; ///< The flags. +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Flags_h_ diff --git a/include/lldb/Core/History.h b/include/lldb/Core/History.h new file mode 100644 index 0000000..b362688 --- /dev/null +++ b/include/lldb/Core/History.h @@ -0,0 +1,177 @@ +//===-- History.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_History_h_ +#define lldb_History_h_ + +// C Includes +#include <stdint.h> + +// C++ Includes +#include <stack> +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class HistorySource History.h "lldb/Core/History.h" +/// @brief A class that defines history events. +//---------------------------------------------------------------------- + +class HistorySource +{ +public: + typedef const void * HistoryEvent; + + HistorySource () : + m_mutex (Mutex::eMutexTypeRecursive), + m_events () + { + } + + virtual + ~HistorySource() + { + } + + // Create a new history event. Subclasses should use any data or members + // in the subclass of this class to produce a history event and push it + // onto the end of the history stack. + + virtual HistoryEvent + CreateHistoryEvent () = 0; + + virtual void + DeleteHistoryEvent (HistoryEvent event) = 0; + + virtual void + DumpHistoryEvent (Stream &strm, HistoryEvent event) = 0; + + virtual size_t + GetHistoryEventCount() = 0; + + virtual HistoryEvent + GetHistoryEventAtIndex (uint32_t idx) = 0; + + virtual HistoryEvent + GetCurrentHistoryEvent () = 0; + + // Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs. + virtual int + CompareHistoryEvents (const HistoryEvent lhs, + const HistoryEvent rhs) = 0; + + virtual bool + IsCurrentHistoryEvent (const HistoryEvent event) = 0; + +private: + typedef std::stack<HistoryEvent> collection; + + Mutex m_mutex; + collection m_events; + + DISALLOW_COPY_AND_ASSIGN (HistorySource); + +}; + +//---------------------------------------------------------------------- +/// @class HistorySourceUInt History.h "lldb/Core/History.h" +/// @brief A class that defines history events that are represented by +/// unsigned integers. +/// +/// Any history event that is defined by a unique monotonically +/// increasing unsigned integer +//---------------------------------------------------------------------- + +class HistorySourceUInt : public HistorySource +{ + HistorySourceUInt (const char *id_name, uintptr_t start_value = 0u) : + HistorySource(), + m_name (id_name), + m_curr_id (start_value) + { + } + + virtual + ~HistorySourceUInt() + { + } + + // Create a new history event. Subclasses should use any data or members + // in the subclass of this class to produce a history event and push it + // onto the end of the history stack. + + virtual HistoryEvent + CreateHistoryEvent () + { + ++m_curr_id; + return (HistoryEvent)m_curr_id; + } + + virtual void + DeleteHistoryEvent (HistoryEvent event) + { + // Nothing to delete, the event contains the integer + } + + virtual void + DumpHistoryEvent (Stream &strm, HistoryEvent event); + + virtual size_t + GetHistoryEventCount() + { + return m_curr_id; + } + + virtual HistoryEvent + GetHistoryEventAtIndex (uint32_t idx) + { + return (HistoryEvent)((uintptr_t)idx); + } + + virtual HistoryEvent + GetCurrentHistoryEvent () + { + return (HistoryEvent)m_curr_id; + } + + // Return 0 when lhs == rhs, 1 if lhs > rhs, or -1 if lhs < rhs. + virtual int + CompareHistoryEvents (const HistoryEvent lhs, + const HistoryEvent rhs) + { + uintptr_t lhs_uint = (uintptr_t)lhs; + uintptr_t rhs_uint = (uintptr_t)rhs; + if (lhs_uint < rhs_uint) + return -1; + if (lhs_uint > rhs_uint) + return +1; + return 0; + } + + virtual bool + IsCurrentHistoryEvent (const HistoryEvent event) + { + return (uintptr_t)event == m_curr_id; + } + +protected: + std::string m_name; // The name of the history unsigned integer + uintptr_t m_curr_id; // The current value of the history unsigned unteger +}; + + +} // namespace lldb_private + +#endif // lldb_History_h_ diff --git a/include/lldb/Core/IOStreamMacros.h b/include/lldb/Core/IOStreamMacros.h new file mode 100644 index 0000000..cc4eeb0 --- /dev/null +++ b/include/lldb/Core/IOStreamMacros.h @@ -0,0 +1,38 @@ +//===-- IOStreamMacros.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_IOStreamMacros_h_ +#define liblldb_IOStreamMacros_h_ +#if defined(__cplusplus) + +#include <iomanip> + +#define RAW_HEXBASE std::setfill('0') << std::hex << std::right +#define HEXBASE '0' << 'x' << RAW_HEXBASE +#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)(x)) +#define RAWHEX16 RAW_HEXBASE << std::setw(4) +#define RAWHEX32 RAW_HEXBASE << std::setw(8) +#define RAWHEX64 RAW_HEXBASE << std::setw(16) +#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x)) +#define HEX16 HEXBASE << std::setw(4) +#define HEX32 HEXBASE << std::setw(8) +#define HEX64 HEXBASE << std::setw(16) +#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x)*2) << (x) +#define HEX(x) HEXBASE << std::setw(sizeof(x)*2) << (x) +#define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x) +#define STRING_WIDTH(w) std::setfill(' ') << std::setw(w) +#define LEFT_STRING_WIDTH(s, w) std::left << std::setfill(' ') << std::setw(w) << (s) << std::right +#define DECIMAL std::dec << std::setfill(' ') +#define DECIMAL_WIDTH(w) DECIMAL << std::setw(w) +//#define FLOAT(n, d) std::setfill(' ') << std::setw((n)+(d)+1) << std::setprecision(d) << std::showpoint << std::fixed +#define INDENT_WITH_SPACES(iword_idx) std::setfill(' ') << std::setw((iword_idx)) << "" +#define INDENT_WITH_TABS(iword_idx) std::setfill('\t') << std::setw((iword_idx)) << "" + +#endif // #if defined(__cplusplus) +#endif // liblldb_IOStreamMacros_h_ diff --git a/include/lldb/Core/InputReader.h b/include/lldb/Core/InputReader.h new file mode 100644 index 0000000..fa86e9a --- /dev/null +++ b/include/lldb/Core/InputReader.h @@ -0,0 +1,274 @@ +//===-- InputReader.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_InputReader_h_ +#define liblldb_InputReader_h_ + +#include <string.h> + +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/StringList.h" +#include "lldb/Host/Predicate.h" + + +namespace lldb_private { + +class InputReader +{ +public: + + typedef size_t (*Callback) (void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + struct HandlerData + { + InputReader& reader; + const char *bytes; + size_t bytes_len; + void* baton; + + HandlerData(InputReader& r, + const char* b, + size_t l, + void* t) : + reader(r), + bytes(b), + bytes_len(l), + baton(t) + { + } + + lldb::StreamSP + GetOutStream(); + + bool + GetBatchMode(); + }; + + struct InitializationParameters + { + private: + void* m_baton; + lldb::InputReaderGranularity m_token_size; + char* m_end_token; + char* m_prompt; + bool m_echo; + bool m_save_user_input; + public: + InitializationParameters() : + m_baton(NULL), + m_token_size(lldb::eInputReaderGranularityLine), + m_echo(true), + m_save_user_input(false) + { + SetEndToken("DONE"); + SetPrompt("> "); + } + + InitializationParameters& + SetEcho(bool e) + { + m_echo = e; + return *this; + } + + InitializationParameters& + SetSaveUserInput(bool s) + { + m_save_user_input = s; + return *this; + } + + InitializationParameters& + SetBaton(void* b) + { + m_baton = b; + return *this; + } + + InitializationParameters& + SetGranularity(lldb::InputReaderGranularity g) + { + m_token_size = g; + return *this; + } + + InitializationParameters& + SetEndToken(const char* e) + { + m_end_token = new char[strlen(e)+1]; + ::strcpy(m_end_token,e); + return *this; + } + + InitializationParameters& + SetPrompt(const char* p) + { + m_prompt = new char[strlen(p)+1]; + ::strcpy(m_prompt,p); + return *this; + } + + friend class InputReaderEZ; + + }; + + InputReader (Debugger &debugger); + + virtual + ~InputReader (); + + virtual Error + Initialize (Callback callback, + void *baton, + lldb::InputReaderGranularity token_size, + const char *end_token, + const char *prompt, + bool echo); + + virtual Error Initialize(void* baton, + lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, + const char* end_token = "DONE", + const char *prompt = "> ", + bool echo = true) + { + return Error("unimplemented"); + } + + virtual Error + Initialize(InitializationParameters& params) + { + return Error("unimplemented"); + } + + // to use these handlers instead of the Callback function, you must subclass + // InputReaderEZ, and redefine the handlers for the events you care about + virtual void + ActivateHandler(HandlerData&) {} + + virtual void + DeactivateHandler(HandlerData&) {} + + virtual void + ReactivateHandler(HandlerData&) {} + + virtual void + AsynchronousOutputWrittenHandler(HandlerData&) {} + + virtual void + GotTokenHandler(HandlerData&) {} + + virtual void + InterruptHandler(HandlerData&) {} + + virtual void + EOFHandler(HandlerData&) {} + + virtual void + DoneHandler(HandlerData&) {} + + bool + IsDone () const + { + return m_done; + } + + void + SetIsDone (bool b) + { + m_done = b; + } + + lldb::InputReaderGranularity + GetGranularity () const + { + return m_granularity; + } + + bool + GetEcho () const + { + return m_echo; + } + + StringList& + GetUserInput() + { + return m_user_input; + } + + virtual bool + GetSaveUserInput() + { + return false; + } + + // Subclasses _can_ override this function to get input as it comes in + // without any granularity + virtual size_t + HandleRawBytes (const char *bytes, size_t bytes_len); + + Debugger & + GetDebugger() + { + return m_debugger; + } + + bool + IsActive () const + { + return m_active; + } + + const char * + GetPrompt () const; + + void + RefreshPrompt(); + + // If you want to read from an input reader synchronously, then just initialize the + // reader and then call WaitOnReaderIsDone, which will return when the reader is popped. + void + WaitOnReaderIsDone (); + + static const char * + GranularityAsCString (lldb::InputReaderGranularity granularity); + +protected: + friend class Debugger; + + void + Notify (lldb::InputReaderAction notification); + + Debugger &m_debugger; + Callback m_callback; + void *m_callback_baton; + std::string m_end_token; + std::string m_prompt; + lldb::InputReaderGranularity m_granularity; + bool m_done; + bool m_echo; + bool m_active; + Predicate<bool> m_reader_done; + StringList m_user_input; + bool m_save_user_input; + +private: + DISALLOW_COPY_AND_ASSIGN (InputReader); + +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_InputReader_h_ diff --git a/include/lldb/Core/InputReaderEZ.h b/include/lldb/Core/InputReaderEZ.h new file mode 100644 index 0000000..85561b6 --- /dev/null +++ b/include/lldb/Core/InputReaderEZ.h @@ -0,0 +1,87 @@ +//===-- InputReaderEZ.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_InputReaderEZ_h_ +#define liblldb_InputReaderEZ_h_ + +#include "lldb/Core/InputReader.h" + +namespace lldb_private { + +class InputReaderEZ : public InputReader +{ + +private: + + static size_t Callback_Impl(void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); +public: + + InputReaderEZ (Debugger &debugger) : + InputReader(debugger) + {} + + virtual + ~InputReaderEZ (); + + using InputReader::Initialize; + virtual Error + Initialize(void* baton, + lldb::InputReaderGranularity token_size = lldb::eInputReaderGranularityLine, + const char* end_token = "DONE", + const char *prompt = "> ", + bool echo = true); + + virtual Error + Initialize(InitializationParameters& params); + + virtual void + ActivateHandler(HandlerData&) {} + + virtual void + DeactivateHandler(HandlerData&) {} + + virtual void + ReactivateHandler(HandlerData&) {} + + virtual void + AsynchronousOutputWrittenHandler(HandlerData&) {} + + virtual void + GotTokenHandler(HandlerData&) {} + + virtual void + InterruptHandler(HandlerData&) {} + + virtual void + EOFHandler(HandlerData&) {} + + virtual void + DoneHandler(HandlerData&) {} + + virtual bool + GetSaveUserInput() + { + return m_save_user_input; + } + +protected: + friend class Debugger; + +private: + DISALLOW_COPY_AND_ASSIGN (InputReaderEZ); + +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_InputReaderEZ_h_ diff --git a/include/lldb/Core/InputReaderStack.h b/include/lldb/Core/InputReaderStack.h new file mode 100644 index 0000000..a73b97c --- /dev/null +++ b/include/lldb/Core/InputReaderStack.h @@ -0,0 +1,58 @@ +//===-- InputReaderStack.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_InputReaderStack_h_ +#define liblldb_InputReaderStack_h_ + +#include <stack> + +#include "lldb/lldb-private.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class InputReaderStack +{ +public: + + InputReaderStack (); + + ~InputReaderStack (); + + size_t + GetSize () const; + + void + Push (const lldb::InputReaderSP& reader_sp); + + bool + IsEmpty () const; + + lldb::InputReaderSP + Top (); + + void + Pop (); + + Mutex & + GetStackMutex (); + +protected: + + std::stack<lldb::InputReaderSP> m_input_readers; + mutable Mutex m_input_readers_mutex; + +private: + + DISALLOW_COPY_AND_ASSIGN (InputReaderStack); +}; + +} // namespace lldb_private + +#endif // liblldb_InputReaderStack_h_ diff --git a/include/lldb/Core/Language.h b/include/lldb/Core/Language.h new file mode 100644 index 0000000..670c6aa --- /dev/null +++ b/include/lldb/Core/Language.h @@ -0,0 +1,117 @@ +//===-- Language.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_Language_h_ +#define liblldb_Language_h_ + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Language Language.h "lldb/Core/Language.h" +/// @brief Encapsulates the programming language for an lldb object. +/// +/// Languages are represented by an enumeration value. +/// +/// The enumeration values used when describing the programming language +/// are the same values as the latest DWARF specification. +//---------------------------------------------------------------------- +class Language +{ +public: + //------------------------------------------------------------------ + /// Construct with optional language enumeration. + //------------------------------------------------------------------ + Language(lldb::LanguageType language = lldb::eLanguageTypeUnknown); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual in case this class is subclassed. + //------------------------------------------------------------------ + virtual + ~Language(); + + //------------------------------------------------------------------ + /// Get the language value as a NULL termianted C string. + /// + /// @return + /// The C string representation of the language. The returned + /// string does not need to be freed as it comes from constant + /// strings. NULL can be returned when the language is set to + /// a value that doesn't match of of the lldb::LanguageType + /// enumerations. + //------------------------------------------------------------------ + const char * + AsCString (lldb::DescriptionLevel level = lldb::eDescriptionLevelBrief) const; + + void + Clear(); + + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Dump the language value to the stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the language description. + //------------------------------------------------------------------ + void + Dump(Stream *s) const; + + //------------------------------------------------------------------ + /// Get accessor for the language. + /// + /// @return + /// The enumeration value that describes the programming + /// language that an object is associated with. + //------------------------------------------------------------------ + virtual lldb::LanguageType + GetLanguage() const; + + //------------------------------------------------------------------ + /// Set accessor for the language. + /// + /// @param[in] language + /// The new enumeration value that describes the programming + /// language that an object is associated with. + //------------------------------------------------------------------ + void + SetLanguage(lldb::LanguageType language); + + //------------------------------------------------------------------ + /// Set accessor for the language. + /// + /// @param[in] language_cstr + /// The language name as a C string. + //------------------------------------------------------------------ + bool + SetLanguageFromCString(const char *language_cstr); + + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + lldb::LanguageType m_language; ///< The programming language enumeration value. + ///< The enumeration values are the same as the + ///< latest DWARF specification. +}; + +//-------------------------------------------------------------- +/// Stream the language enumeration as a string object to a +/// Stream. +//-------------------------------------------------------------- +Stream& operator << (Stream& s, const Language& language); + +} // namespace lldb_private + +#endif // liblldb_Language_h_ diff --git a/include/lldb/Core/Listener.h b/include/lldb/Core/Listener.h new file mode 100644 index 0000000..a12a65d --- /dev/null +++ b/include/lldb/Core/Listener.h @@ -0,0 +1,194 @@ +//===-- Listener.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_Select_h_ +#define liblldb_Select_h_ + +// C Includes +// C++ Includes +#include <list> +#include <map> +#include <set> +#include <string> +#include <vector> + + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Host/Predicate.h" +#include "lldb/Core/Event.h" + +namespace lldb_private { + +class Listener +{ +public: + typedef bool (*HandleBroadcastCallback) (lldb::EventSP &event_sp, void *baton); + + friend class Broadcaster; + friend class BroadcasterManager; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Listener (const char *name); + + ~Listener (); + + void + AddEvent (lldb::EventSP &event); + + void + Clear (); + + const char * + GetName () + { + return m_name.c_str(); + } + + uint32_t + StartListeningForEventSpec (BroadcasterManager &manager, + const BroadcastEventSpec &event_spec); + + bool + StopListeningForEventSpec (BroadcasterManager &manager, + const BroadcastEventSpec &event_spec); + + uint32_t + StartListeningForEvents (Broadcaster* broadcaster, + uint32_t event_mask); + + uint32_t + StartListeningForEvents (Broadcaster* broadcaster, + uint32_t event_mask, + HandleBroadcastCallback callback, + void *callback_user_data); + + bool + StopListeningForEvents (Broadcaster* broadcaster, + uint32_t event_mask); + + // Returns true if an event was recieved, false if we timed out. + bool + WaitForEvent (const TimeValue *timeout, + lldb::EventSP &event_sp); + + bool + WaitForEventForBroadcaster (const TimeValue *timeout, + Broadcaster *broadcaster, + lldb::EventSP &event_sp); + + bool + WaitForEventForBroadcasterWithType (const TimeValue *timeout, + Broadcaster *broadcaster, + uint32_t event_type_mask, + lldb::EventSP &event_sp); + + Event * + PeekAtNextEvent (); + + Event * + PeekAtNextEventForBroadcaster (Broadcaster *broadcaster); + + Event * + PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, + uint32_t event_type_mask); + + bool + GetNextEvent (lldb::EventSP &event_sp); + + bool + GetNextEventForBroadcaster (Broadcaster *broadcaster, + lldb::EventSP &event_sp); + + bool + GetNextEventForBroadcasterWithType (Broadcaster *broadcaster, + uint32_t event_type_mask, + lldb::EventSP &event_sp); + + size_t + HandleBroadcastEvent (lldb::EventSP &event_sp); + +private: + + //------------------------------------------------------------------ + // Classes that inherit from Listener can see and modify these + //------------------------------------------------------------------ + struct BroadcasterInfo + { + BroadcasterInfo(uint32_t mask, HandleBroadcastCallback cb = NULL, void *ud = NULL) : + event_mask (mask), + callback (cb), + callback_user_data (ud) + { + } + + uint32_t event_mask; + HandleBroadcastCallback callback; + void *callback_user_data; + }; + + typedef std::multimap<Broadcaster*, BroadcasterInfo> broadcaster_collection; + typedef std::list<lldb::EventSP> event_collection; + typedef std::vector<BroadcasterManager *> broadcaster_manager_collection; + + bool + FindNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster + const ConstString *sources, // NULL for any event + uint32_t num_sources, + uint32_t event_type_mask, + lldb::EventSP &event_sp, + bool remove); + + bool + GetNextEventInternal (Broadcaster *broadcaster, // NULL for any broadcaster + const ConstString *sources, // NULL for any event + uint32_t num_sources, + uint32_t event_type_mask, + lldb::EventSP &event_sp); + + bool + WaitForEventsInternal (const TimeValue *timeout, + Broadcaster *broadcaster, // NULL for any broadcaster + const ConstString *sources, // NULL for any event + uint32_t num_sources, + uint32_t event_type_mask, + lldb::EventSP &event_sp); + + std::string m_name; + broadcaster_collection m_broadcasters; + Mutex m_broadcasters_mutex; // Protects m_broadcasters + event_collection m_events; + Mutex m_events_mutex; // Protects m_broadcasters and m_events + Predicate<bool> m_cond_wait; + broadcaster_manager_collection m_broadcaster_managers; + + void + BroadcasterWillDestruct (Broadcaster *); + + void + BroadcasterManagerWillDestruct (BroadcasterManager *manager); + + +// broadcaster_collection::iterator +// FindBroadcasterWithMask (Broadcaster *broadcaster, +// uint32_t event_mask, +// bool exact); + + //------------------------------------------------------------------ + // For Listener only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (Listener); +}; + +} // namespace lldb_private + +#endif // liblldb_Select_h_ diff --git a/include/lldb/Core/Log.h b/include/lldb/Core/Log.h new file mode 100644 index 0000000..ced6f25 --- /dev/null +++ b/include/lldb/Core/Log.h @@ -0,0 +1,236 @@ +//===-- Log.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_Log_h_ +#define liblldb_Log_h_ + +// C Includes +#include <stdbool.h> +#include <stdint.h> +#include <signal.h> +#include <stdio.h> +#include <unistd.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Flags.h" +#include "lldb/Core/PluginInterface.h" + +//---------------------------------------------------------------------- +// Logging types +//---------------------------------------------------------------------- +#define LLDB_LOG_FLAG_STDOUT (1u << 0) +#define LLDB_LOG_FLAG_STDERR (1u << 1) +#define LLDB_LOG_FLAG_FATAL (1u << 2) +#define LLDB_LOG_FLAG_ERROR (1u << 3) +#define LLDB_LOG_FLAG_WARNING (1u << 4) +#define LLDB_LOG_FLAG_DEBUG (1u << 5) +#define LLDB_LOG_FLAG_VERBOSE (1u << 6) + +//---------------------------------------------------------------------- +// Logging Options +//---------------------------------------------------------------------- +#define LLDB_LOG_OPTION_THREADSAFE (1u << 0) +#define LLDB_LOG_OPTION_VERBOSE (1u << 1) +#define LLDB_LOG_OPTION_DEBUG (1u << 2) +#define LLDB_LOG_OPTION_PREPEND_SEQUENCE (1u << 3) +#define LLDB_LOG_OPTION_PREPEND_TIMESTAMP (1u << 4) +#define LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD (1u << 5) +#define LLDB_LOG_OPTION_PREPEND_THREAD_NAME (1U << 6) +#define LLDB_LOG_OPTION_BACKTRACE (1U << 7) + +//---------------------------------------------------------------------- +// Logging Functions +//---------------------------------------------------------------------- +namespace lldb_private { + +class Log +{ +public: + + //------------------------------------------------------------------ + // Callback definitions for abstracted plug-in log access. + //------------------------------------------------------------------ + typedef void (*DisableCallback) (const char **categories, Stream *feedback_strm); + typedef Log * (*EnableCallback) (lldb::StreamSP &log_stream_sp, + uint32_t log_options, + const char **categories, + Stream *feedback_strm); + typedef void (*ListCategoriesCallback) (Stream *strm); + + struct Callbacks + { + DisableCallback disable; + EnableCallback enable; + ListCategoriesCallback list_categories; + }; + + //------------------------------------------------------------------ + // Static accessors for logging channels + //------------------------------------------------------------------ + static void + RegisterLogChannel (const ConstString &channel, + const Log::Callbacks &log_callbacks); + + static bool + UnregisterLogChannel (const ConstString &channel); + + static bool + GetLogChannelCallbacks (const ConstString &channel, + Log::Callbacks &log_callbacks); + + + static void + EnableAllLogChannels (lldb::StreamSP &log_stream_sp, + uint32_t log_options, + const char **categories, + Stream *feedback_strm); + + static void + DisableAllLogChannels (Stream *feedback_strm); + + static void + ListAllLogChannels (Stream *strm); + + static void + Initialize (); + + static void + Terminate (); + + //------------------------------------------------------------------ + // Auto completion + //------------------------------------------------------------------ + static void + AutoCompleteChannelName (const char *channel_name, + StringList &matches); + + //------------------------------------------------------------------ + // Member functions + //------------------------------------------------------------------ + Log (); + + Log (const lldb::StreamSP &stream_sp); + + ~Log (); + + void + PutCString (const char *cstr); + + void + Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + void + VAPrintf (const char *format, va_list args); + + void + PrintfWithFlags( uint32_t flags, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + + void + LogIf (uint32_t mask, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); + + void + Debug (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + + void + DebugVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + + void + Error (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + + void + FatalError (int err, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); + + void + Verbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + + void + Warning (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + + void + WarningVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); + + Flags & + GetOptions(); + + const Flags & + GetOptions() const; + + Flags & + GetMask(); + + const Flags & + GetMask() const; + + bool + GetVerbose() const; + + bool + GetDebug() const; + + void + SetStream (const lldb::StreamSP &stream_sp) + { + m_stream_sp = stream_sp; + } + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + lldb::StreamSP m_stream_sp; + Flags m_options; + Flags m_mask_bits; + + void + PrintfWithFlagsVarArg (uint32_t flags, const char *format, va_list args); + +private: + DISALLOW_COPY_AND_ASSIGN (Log); +}; + + +class LogChannel : public PluginInterface +{ +public: + LogChannel (); + + virtual + ~LogChannel (); + + static lldb::LogChannelSP + FindPlugin (const char *plugin_name); + + // categories is a an array of chars that ends with a NULL element. + virtual void + Disable (const char **categories, Stream *feedback_strm) = 0; + + virtual bool + Enable (lldb::StreamSP &log_stream_sp, + uint32_t log_options, + Stream *feedback_strm, // Feedback stream for argument errors etc + const char **categories) = 0;// The categories to enable within this logging stream, if empty, enable default set + + virtual void + ListCategories (Stream *strm) = 0; + +protected: + std::unique_ptr<Log> m_log_ap; + +private: + DISALLOW_COPY_AND_ASSIGN (LogChannel); +}; + + +} // namespace lldb_private + +#endif // liblldb_Log_H_ diff --git a/include/lldb/Core/Mangled.h b/include/lldb/Core/Mangled.h new file mode 100644 index 0000000..8732dc0 --- /dev/null +++ b/include/lldb/Core/Mangled.h @@ -0,0 +1,306 @@ +//===-- Mangled.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_Mangled_h_ +#define liblldb_Mangled_h_ +#if defined(__cplusplus) + + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include <vector> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Mangled Mangled.h "lldb/Core/Mangled.h" +/// @brief A class that handles mangled names. +/// +/// Designed to handle mangled names. The demangled version of any names +/// will be computed when the demangled name is accessed through the +/// Demangled() acccessor. This class can also tokenize the demangled +/// version of the name for powerful searches. Functions and symbols +/// could make instances of this class for their mangled names. Uniqued +/// string pools are used for the mangled, demangled, and token string +/// values to allow for faster comparisons and for efficient memory use. +//---------------------------------------------------------------------- +class Mangled +{ +public: + + enum NamePreference + { + ePreferMangled, + ePreferDemangled + }; + + //---------------------------------------------------------------------- + /// Default constructor. + /// + /// Initialize with both mangled and demangled names empty. + //---------------------------------------------------------------------- + Mangled (); + + //---------------------------------------------------------------------- + /// Construct with name. + /// + /// Constructor with an optional string and a boolean indicating if it is + /// the mangled version. + /// + /// @param[in] name + /// The already const name to copy into this object. + /// + /// @param[in] is_mangled + /// If \b true then \a name is a mangled name, if \b false then + /// \a name is demangled. + //---------------------------------------------------------------------- + explicit + Mangled (const ConstString &name, bool is_mangled); + + //---------------------------------------------------------------------- + /// Construct with name. + /// + /// Constructor with an optional string and auto-detect if \a name is + /// mangled or not. + /// + /// @param[in] name + /// The already const name to copy into this object. + //---------------------------------------------------------------------- + explicit + Mangled (const ConstString &name); + + //---------------------------------------------------------------------- + /// Destructor + /// + /// Releases its ref counts on the mangled and demangled strings that + /// live in the global string pool. + //---------------------------------------------------------------------- + ~Mangled (); + + //---------------------------------------------------------------------- + /// Convert to pointer operator. + /// + /// This allows code to check a Mangled object to see if it contains + /// a valid mangled name using code such as: + /// + /// @code + /// Mangled mangled(...); + /// if (mangled) + /// { ... + /// @endcode + /// + /// @return + /// A pointer to this object if either the mangled or unmangled + /// name is set, NULL otherwise. + //---------------------------------------------------------------------- + operator + void*() const; + + //---------------------------------------------------------------------- + /// Logical NOT operator. + /// + /// This allows code to check a Mangled object to see if it contains + /// an empty mangled name using code such as: + /// + /// @code + /// Mangled mangled(...); + /// if (!mangled) + /// { ... + /// @endcode + /// + /// @return + /// Returns \b true if the object has an empty mangled and + /// unmangled name, \b false otherwise. + //---------------------------------------------------------------------- + bool + operator!() const; + + //---------------------------------------------------------------------- + /// Clear the mangled and demangled values. + //---------------------------------------------------------------------- + void + Clear (); + + //---------------------------------------------------------------------- + /// Compare the mangled string values + /// + /// Compares the Mangled::GetName() string in \a lhs and \a rhs. + /// + /// @param[in] lhs + /// A const reference to the Left Hand Side object to compare. + /// + /// @param[in] rhs + /// A const reference to the Right Hand Side object to compare. + /// + /// @return + /// @li -1 if \a lhs is less than \a rhs + /// @li 0 if \a lhs is equal to \a rhs + /// @li 1 if \a lhs is greater than \a rhs + //---------------------------------------------------------------------- + static int + Compare (const Mangled& lhs, const Mangled& rhs); + + //---------------------------------------------------------------------- + /// Dump a description of this object to a Stream \a s. + /// + /// Dump a Mangled object to stream \a s. We don't force our + /// demangled name to be computed currently (we don't use the accessor). + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //---------------------------------------------------------------------- + void + Dump (Stream *s) const; + + //---------------------------------------------------------------------- + /// Dump a debug description of this object to a Stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //---------------------------------------------------------------------- + void + DumpDebug (Stream *s) const; + + //---------------------------------------------------------------------- + /// Demangled name get accessor. + /// + /// @return + /// A const reference to the demangled name string object. + //---------------------------------------------------------------------- + const ConstString& + GetDemangledName () const; + + void + SetDemangledName (const ConstString &name) + { + m_demangled = name; + } + + void + SetMangledName (const ConstString &name) + { + m_mangled = name; + } + + //---------------------------------------------------------------------- + /// Mangled name get accessor. + /// + /// @return + /// A reference to the mangled name string object. + //---------------------------------------------------------------------- + ConstString& + GetMangledName () + { + return m_mangled; + } + + //---------------------------------------------------------------------- + /// Mangled name get accessor. + /// + /// @return + /// A const reference to the mangled name string object. + //---------------------------------------------------------------------- + const ConstString& + GetMangledName () const + { + return m_mangled; + } + + //---------------------------------------------------------------------- + /// Best name get accessor. + /// + /// @param[in] preference + /// Which name would you prefer to get? + /// + /// @return + /// A const reference to the the preferred name string object if this + /// object has a valid name of that kind, else a const reference to the + /// other name is returned. + //---------------------------------------------------------------------- + const ConstString& + GetName (NamePreference preference = ePreferDemangled) const; + + //---------------------------------------------------------------------- + /// Check if "name" matches either the mangled or demangled name. + /// + /// @param[in] name + /// A name to match against both strings. + /// + /// @return + /// \b True if \a name matches either name, \b false otherwise. + //---------------------------------------------------------------------- + bool + NameMatches (const ConstString &name) const + { + if (m_mangled == name) + return true; + return GetDemangledName () == name; + } + + bool + NameMatches (const RegularExpression& regex) const; + + //---------------------------------------------------------------------- + /// Get the memory cost of this object. + /// + /// Return the size in bytes that this object takes in memory. This + /// returns the size in bytes of this object, not any shared string + /// values it may refer to. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// + /// @see ConstString::StaticMemorySize () + //---------------------------------------------------------------------- + size_t + MemorySize () const; + + //---------------------------------------------------------------------- + /// Set the string value in this object. + /// + /// If \a is_mangled is \b true, then the mangled named is set to \a + /// name, else the demangled name is set to \a name. + /// + /// @param[in] name + /// The already const version of the name for this object. + /// + /// @param[in] is_mangled + /// If \b true then \a name is a mangled name, if \b false then + /// \a name is demangled. + //---------------------------------------------------------------------- + void + SetValue (const ConstString &name, bool is_mangled); + + //---------------------------------------------------------------------- + /// Set the string value in this object. + /// + /// This version auto detects if the string is mangled by inspecting the + /// string value and looking for common mangling prefixes. + /// + /// @param[in] name + /// The already const version of the name for this object. + //---------------------------------------------------------------------- + void + SetValue (const ConstString &name); + +private: + //---------------------------------------------------------------------- + /// Mangled member variables. + //---------------------------------------------------------------------- + ConstString m_mangled; ///< The mangled version of the name + mutable ConstString m_demangled; ///< Mutable so we can get it on demand with a const version of this object +}; + + +Stream& operator << (Stream& s, const Mangled& obj); + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Mangled_h_ diff --git a/include/lldb/Core/MappedHash.h b/include/lldb/Core/MappedHash.h new file mode 100644 index 0000000..80d249d --- /dev/null +++ b/include/lldb/Core/MappedHash.h @@ -0,0 +1,552 @@ +// +// MappedHash.h +// + +#ifndef liblldb_MappedHash_h_ +#define liblldb_MappedHash_h_ + +#include <assert.h> +#include <stdint.h> + +#include <map> +#include <vector> + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Stream.h" + +class MappedHash +{ +public: + + enum HashFunctionType + { + eHashFunctionDJB = 0u // Daniel J Bernstein hash function that is also used by the ELF GNU_HASH sections + }; + + + static uint32_t + HashStringUsingDJB (const char *s) + { + uint32_t h = 5381; + + for (unsigned char c = *s; c; c = *++s) + h = ((h << 5) + h) + c; + + return h; + } + + static uint32_t + HashString (uint32_t hash_function, const char *s) + { + switch (hash_function) + { + case MappedHash::eHashFunctionDJB: + return HashStringUsingDJB (s); + + default: + break; + } + assert (!"Invalid hash function index"); + return 0; + } + + + static const uint32_t HASH_MAGIC = 0x48415348u; + static const uint32_t HASH_CIGAM = 0x48534148u; + + template <typename T> + struct Header + { + typedef T HeaderData; + + uint32_t magic; // HASH_MAGIC or HASH_CIGAM magic value to allow endian detection + uint16_t version; // Version number + uint16_t hash_function; // The hash function enumeration that was used + uint32_t bucket_count; // The number of buckets in this hash table + uint32_t hashes_count; // The total number of unique hash values and hash data offsets in this table + uint32_t header_data_len; // The size in bytes of the "header_data" template member below + HeaderData header_data; // + + Header () : + magic (HASH_MAGIC), + version (1), + hash_function (eHashFunctionDJB), + bucket_count (0), + hashes_count (0), + header_data_len (sizeof(T)), + header_data () + { + } + + virtual + ~Header() + { + } + + size_t + GetByteSize() const + { + return sizeof(magic) + + sizeof(version) + + sizeof(hash_function) + + sizeof(bucket_count) + + sizeof(hashes_count) + + sizeof(header_data_len) + + header_data_len; + } + + virtual size_t + GetByteSize (const HeaderData &header_data) = 0; + + void + SetHeaderDataByteSize (uint32_t header_data_byte_size) + { + header_data_len = header_data_byte_size; + } + + void + Dump (lldb_private::Stream &s) + { + s.Printf ("header.magic = 0x%8.8x\n", magic); + s.Printf ("header.version = 0x%4.4x\n", version); + s.Printf ("header.hash_function = 0x%4.4x\n", hash_function); + s.Printf ("header.bucket_count = 0x%8.8x %u\n", bucket_count, bucket_count); + s.Printf ("header.hashes_count = 0x%8.8x %u\n", hashes_count, hashes_count); + s.Printf ("header.header_data_len = 0x%8.8x %u\n", header_data_len, header_data_len); + } + + virtual lldb::offset_t + Read (lldb_private::DataExtractor &data, lldb::offset_t offset) + { + if (data.ValidOffsetForDataOfSize (offset, + sizeof (magic) + + sizeof (version) + + sizeof (hash_function) + + sizeof (bucket_count) + + sizeof (hashes_count) + + sizeof (header_data_len))) + { + magic = data.GetU32 (&offset); + if (magic != HASH_MAGIC) + { + if (magic == HASH_CIGAM) + { + switch (data.GetByteOrder()) + { + case lldb::eByteOrderBig: + data.SetByteOrder(lldb::eByteOrderLittle); + break; + case lldb::eByteOrderLittle: + data.SetByteOrder(lldb::eByteOrderBig); + break; + default: + return LLDB_INVALID_OFFSET; + } + } + else + { + // Magic bytes didn't match + version = 0; + return LLDB_INVALID_OFFSET; + } + } + + version = data.GetU16 (&offset); + if (version != 1) + { + // Unsupported version + return LLDB_INVALID_OFFSET; + } + hash_function = data.GetU16 (&offset); + if (hash_function == 4) + hash_function = 0; // Deal with pre-release version of this table... + bucket_count = data.GetU32 (&offset); + hashes_count = data.GetU32 (&offset); + header_data_len = data.GetU32 (&offset); + return offset; + } + return LLDB_INVALID_OFFSET; + } +// +// // Returns a buffer that contains a serialized version of this table +// // that must be freed with free(). +// virtual void * +// Write (int fd); + }; + + template <typename __KeyType, class __HeaderDataType, class __ValueType> + class ExportTable + { + public: + typedef __HeaderDataType HeaderDataType; + typedef Header<HeaderDataType> HeaderType; + typedef __KeyType KeyType; + typedef __ValueType ValueType; + + struct Entry + { + uint32_t hash; + KeyType key; + ValueType value; + }; + + typedef std::vector<ValueType> ValueArrayType; + + typedef std::map<KeyType, ValueArrayType> HashData; + // Map a name hash to one or more name infos + typedef std::map<uint32_t, HashData> HashToHashData; + + virtual KeyType + GetKeyForStringType (const char *cstr) const = 0; + + virtual size_t + GetByteSize (const HashData &key_to_key_values) = 0; + + virtual bool + WriteHashData (const HashData &hash_data, + lldb_private::Stream &ostrm) = 0; +// + void + AddEntry (const char *cstr, const ValueType &value) + { + Entry entry; + entry.hash = MappedHash::HashString (eHashFunctionDJB, cstr); + entry.key = GetKeyForStringType (cstr); + entry.value = value; + m_entries.push_back (entry); + } + + void + Save (const HeaderDataType &header_data, + lldb_private::Stream &ostrm) + { + if (m_entries.empty()) + return; + + const uint32_t num_entries = m_entries.size(); + uint32_t i = 0; + + HeaderType header; + + header.magic = HASH_MAGIC; + header.version = 1; + header.hash_function = eHashFunctionDJB; + header.bucket_count = 0; + header.hashes_count = 0; + header.prologue_length = header_data.GetByteSize(); + + // We need to figure out the number of unique hashes first before we can + // calculate the number of buckets we want to use. + typedef std::vector<uint32_t> hash_coll; + hash_coll unique_hashes; + unique_hashes.resize (num_entries); + for (i=0; i<num_entries; ++i) + unique_hashes[i] = m_entries[i].hash; + std::sort (unique_hashes.begin(), unique_hashes.end()); + hash_coll::iterator pos = std::unique (unique_hashes.begin(), unique_hashes.end()); + const size_t num_unique_hashes = std::distance (unique_hashes.begin(), pos); + + if (num_unique_hashes > 1024) + header.bucket_count = num_unique_hashes/4; + else if (num_unique_hashes > 16) + header.bucket_count = num_unique_hashes/2; + else + header.bucket_count = num_unique_hashes; + if (header.bucket_count == 0) + header.bucket_count = 1; + + + std::vector<HashToHashData> hash_buckets; + std::vector<uint32_t> hash_indexes (header.bucket_count, 0); + std::vector<uint32_t> hash_values; + std::vector<uint32_t> hash_offsets; + hash_buckets.resize (header.bucket_count); + uint32_t bucket_entry_empties = 0; + //StreamString hash_file_data(Stream::eBinary, dwarf->GetObjectFile()->GetAddressByteSize(), dwarf->GetObjectFile()->GetByteSize()); + + // Push all of the hashes into their buckets and create all bucket + // entries all populated with data. + for (i=0; i<num_entries; ++i) + { + const uint32_t hash = m_entries[i].hash; + const uint32_t bucket_idx = hash % header.bucket_count; + const uint32_t strp_offset = m_entries[i].str_offset; + const uint32_t die_offset = m_entries[i].die_offset; + hash_buckets[bucket_idx][hash][strp_offset].push_back(die_offset); + } + + // Now for each bucket we write the bucket value which is the + // number of hashes and the hash index encoded into a single + // 32 bit unsigned integer. + for (i=0; i<header.bucket_count; ++i) + { + HashToHashData &bucket_entry = hash_buckets[i]; + + if (bucket_entry.empty()) + { + // Empty bucket + ++bucket_entry_empties; + hash_indexes[i] = UINT32_MAX; + } + else + { + const uint32_t hash_value_index = hash_values.size(); + uint32_t hash_count = 0; + typename HashToHashData::const_iterator pos, end = bucket_entry.end(); + for (pos = bucket_entry.begin(); pos != end; ++pos) + { + hash_values.push_back (pos->first); + hash_offsets.push_back (GetByteSize (pos->second)); + ++hash_count; + } + + hash_indexes[i] = hash_value_index; + } + } + header.hashes_count = hash_values.size(); + + // Write the header out now that we have the hash_count + header.Write (ostrm); + + // Now for each bucket we write the start index of the hashes + // for the current bucket, or UINT32_MAX if the bucket is empty + for (i=0; i<header.bucket_count; ++i) + { + ostrm.PutHex32(hash_indexes[i]); + } + + // Now we need to write out all of the hash values + for (i=0; i<header.hashes_count; ++i) + { + ostrm.PutHex32(hash_values[i]); + } + + // Now we need to write out all of the hash data offsets, + // there is an offset for each hash in the hashes array + // that was written out above + for (i=0; i<header.hashes_count; ++i) + { + ostrm.PutHex32(hash_offsets[i]); + } + + // Now we write the data for each hash and verify we got the offset + // correct above... + for (i=0; i<header.bucket_count; ++i) + { + HashToHashData &bucket_entry = hash_buckets[i]; + + typename HashToHashData::const_iterator pos, end = bucket_entry.end(); + for (pos = bucket_entry.begin(); pos != end; ++pos) + { + if (!bucket_entry.empty()) + { + WriteHashData (pos->second); + } + } + } + } + protected: + typedef std::vector<Entry> collection; + collection m_entries; + }; + // A class for reading and using a saved hash table from a block of data + // in memory + template <typename __KeyType, class __HeaderType, class __HashData> + class MemoryTable + { + public: + typedef __HeaderType HeaderType; + typedef __KeyType KeyType; + typedef __HashData HashData; + + enum Result + { + eResultKeyMatch = 0u, // The entry was found, key matched and "pair" was filled in successfully + eResultKeyMismatch = 1u, // Bucket hash data collision, but key didn't match + eResultEndOfHashData = 2u, // The chain of items for this hash data in this bucket is terminated, search no more + eResultError = 3u // Error parsing the hash data, abort + }; + + struct Pair + { + KeyType key; + HashData value; + }; + + MemoryTable (lldb_private::DataExtractor &data) : + m_header (), + m_hash_indexes (NULL), + m_hash_values (NULL), + m_hash_offsets (NULL) + { + lldb::offset_t offset = m_header.Read (data, 0); + if (offset != LLDB_INVALID_OFFSET && IsValid ()) + { + m_hash_indexes = (uint32_t *)data.GetData (&offset, m_header.bucket_count * sizeof(uint32_t)); + m_hash_values = (uint32_t *)data.GetData (&offset, m_header.hashes_count * sizeof(uint32_t)); + m_hash_offsets = (uint32_t *)data.GetData (&offset, m_header.hashes_count * sizeof(uint32_t)); + } + } + + virtual + ~MemoryTable () + { + } + + bool + IsValid () const + { + return m_header.version == 1 && + m_header.hash_function == eHashFunctionDJB && + m_header.bucket_count > 0 && + m_header.hashes_count > 0; + } + + uint32_t + GetHashIndex (uint32_t bucket_idx) const + { + if (m_hash_indexes && bucket_idx < m_header.bucket_count) + return m_hash_indexes[bucket_idx]; + return UINT32_MAX; + } + + uint32_t + GetHashValue (uint32_t hash_idx) const + { + if (m_hash_values && hash_idx < m_header.hashes_count) + return m_hash_values[hash_idx]; + return UINT32_MAX; + } + + uint32_t + GetHashDataOffset (uint32_t hash_idx) const + { + if (m_hash_offsets && hash_idx < m_header.hashes_count) + return m_hash_offsets[hash_idx]; + return UINT32_MAX; + } + + bool + Find (const char *name, Pair &pair) const + { + if (IsValid ()) + { + const uint32_t bucket_count = m_header.bucket_count; + const uint32_t hash_count = m_header.hashes_count; + const uint32_t hash_value = MappedHash::HashString (m_header.hash_function, name); + const uint32_t bucket_idx = hash_value % bucket_count; + uint32_t hash_idx = GetHashIndex (bucket_idx); + if (hash_idx < hash_count) + { + for (; hash_idx < hash_count; ++hash_idx) + { + const uint32_t curr_hash_value = GetHashValue (hash_idx); + if (curr_hash_value == hash_value) + { + lldb::offset_t hash_data_offset = GetHashDataOffset (hash_idx); + while (hash_data_offset != UINT32_MAX) + { + const lldb::offset_t prev_hash_data_offset = hash_data_offset; + Result hash_result = GetHashDataForName (name, &hash_data_offset, pair); + // Check the result of getting our hash data + switch (hash_result) + { + case eResultKeyMatch: + return true; + + case eResultKeyMismatch: + if (prev_hash_data_offset == hash_data_offset) + return false; + break; + + case eResultEndOfHashData: + // The last HashData for this key has been reached, stop searching + return false; + case eResultError: + // Error parsing the hash data, abort + return false; + } + } + } + if ((curr_hash_value % bucket_count) != bucket_idx) + break; + } + } + } + return false; + } + + // This method must be implemented in any subclasses. + // The KeyType is user specified and must somehow result in a string + // value. For example, the KeyType might be a string offset in a string + // table and subclasses can store their string table as a member of the + // subclass and return a valie "const char *" given a "key". The value + // could also be a C string pointer, in which case just returning "key" + // will suffice. + + virtual const char * + GetStringForKeyType (KeyType key) const = 0; + + virtual bool + ReadHashData (uint32_t hash_data_offset, + HashData &hash_data) const = 0; + + // This method must be implemented in any subclasses and it must try to + // read one "Pair" at the offset pointed to by the "hash_data_offset_ptr" + // parameter. This offset should be updated as bytes are consumed and + // a value "Result" enum should be returned. If the "name" matches the + // full name for the "pair.key" (which must be filled in by this call), + // then the HashData in the pair ("pair.value") should be extracted and + // filled in and "eResultKeyMatch" should be returned. If "name" doesn't + // match this string for the key, then "eResultKeyMismatch" should be + // returned and all data for the current HashData must be consumed or + // skipped and the "hash_data_offset_ptr" offset needs to be updated to + // point to the next HashData. If the end of the HashData objects for + // a given hash value have been reached, then "eResultEndOfHashData" + // should be returned. If anything else goes wrong during parsing, + // return "eResultError" and the corresponding "Find()" function will + // be canceled and return false. + + virtual Result + GetHashDataForName (const char *name, + lldb::offset_t* hash_data_offset_ptr, + Pair &pair) const = 0; + + const HeaderType & + GetHeader() + { + return m_header; + } + + + void + ForEach (std::function <bool(const HashData &hash_data)> const &callback) const + { + const size_t num_hash_offsets = m_header.hashes_count; + for (size_t i=0; i<num_hash_offsets; ++i) + { + uint32_t hash_data_offset = GetHashDataOffset (i); + if (hash_data_offset != UINT32_MAX) + { + HashData hash_data; + if (ReadHashData (hash_data_offset, hash_data)) + { + // If the callback returns false, then we are done and should stop + if (callback(hash_data) == false) + return; + } + } + } + } + + protected: + // Implementation agnostic information + HeaderType m_header; + uint32_t *m_hash_indexes; + uint32_t *m_hash_values; + uint32_t *m_hash_offsets; + }; + +}; + +#endif // #ifndef liblldb_MappedHash_h_ diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h new file mode 100644 index 0000000..9c13552 --- /dev/null +++ b/include/lldb/Core/Module.h @@ -0,0 +1,1085 @@ +//===-- Module.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_Module_h_ +#define liblldb_Module_h_ + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/UUID.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Host/TimeValue.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Target/PathMappingList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Module Module.h "lldb/Core/Module.h" +/// @brief A class that describes an executable image and its associated +/// object and symbol files. +/// +/// The module is designed to be able to select a single slice of an +/// executable image as it would appear on disk and during program +/// execution. +/// +/// Modules control when and if information is parsed according to which +/// accessors are called. For example the object file (ObjectFile) +/// representation will only be parsed if the object file is requested +/// using the Module::GetObjectFile() is called. The debug symbols +/// will only be parsed if the symbol vendor (SymbolVendor) is +/// requested using the Module::GetSymbolVendor() is called. +/// +/// The module will parse more detailed information as more queries are +/// made. +//---------------------------------------------------------------------- +class Module : + public std::enable_shared_from_this<Module>, + public SymbolContextScope +{ +public: + // Static functions that can track the lifetime of module objects. + // This is handy because we might have Module objects that are in + // shared pointers that aren't in the global module list (from + // ModuleList). If this is the case we need to know about it. + // The modules in the global list maintained by these functions + // can be viewed using the "target modules list" command using the + // "--global" (-g for short). + static size_t + GetNumberAllocatedModules (); + + static Module * + GetAllocatedModuleAtIndex (size_t idx); + + static Mutex * + GetAllocationModuleCollectionMutex(); + + //------------------------------------------------------------------ + /// Construct with file specification and architecture. + /// + /// Clients that wish to share modules with other targets should + /// use ModuleList::GetSharedModule(). + /// + /// @param[in] file_spec + /// The file specification for the on disk repesentation of + /// this executable image. + /// + /// @param[in] arch + /// The architecture to set as the current architecture in + /// this module. + /// + /// @param[in] object_name + /// The name of an object in a module used to extract a module + /// within a module (.a files and modules that contain multiple + /// architectures). + /// + /// @param[in] object_offset + /// The offset within an existing module used to extract a + /// module within a module (.a files and modules that contain + /// multiple architectures). + //------------------------------------------------------------------ + Module (const FileSpec& file_spec, + const ArchSpec& arch, + const ConstString *object_name = NULL, + off_t object_offset = 0, + const TimeValue *object_mod_time_ptr = NULL); + + Module (const ModuleSpec &module_spec); + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + virtual + ~Module (); + + bool + MatchesModuleSpec (const ModuleSpec &module_ref); + + //------------------------------------------------------------------ + /// Set the load address for all sections in a module to be the + /// file address plus \a slide. + /// + /// Many times a module will be loaded in a target with a constant + /// offset applied to all top level sections. This function can + /// set the load address for all top level sections to be the + /// section file address + offset. + /// + /// @param[in] target + /// The target in which to apply the section load addresses. + /// + /// @param[in] offset + /// The offset to apply to all file addresses for all top + /// level sections in the object file as each section load + /// address is being set. + /// + /// @param[out] changed + /// If any section load addresses were changed in \a target, + /// then \a changed will be set to \b true. Else \a changed + /// will be set to false. This allows this function to be + /// called multiple times on the same module for the same + /// target. If the module hasn't moved, then \a changed will + /// be false and no module updated notification will need to + /// be sent out. + /// + /// @return + /// /b True if any sections were successfully loaded in \a target, + /// /b false otherwise. + //------------------------------------------------------------------ + bool + SetLoadAddress (Target &target, + lldb::addr_t offset, + bool &changed); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext (SymbolContext* sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + void + GetDescription (Stream *s, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); + + //------------------------------------------------------------------ + /// Get the module path and object name. + /// + /// Modules can refer to object files. In this case the specification + /// is simple and would return the path to the file: + /// + /// "/usr/lib/foo.dylib" + /// + /// Modules can be .o files inside of a BSD archive (.a file). In + /// this case, the object specification will look like: + /// + /// "/usr/lib/foo.a(bar.o)" + /// + /// There are many places where logging wants to log this fully + /// qualified specification, so we centralize this functionality + /// here. + /// + /// @return + /// The object path + object name if there is one. + //------------------------------------------------------------------ + std::string + GetSpecificationDescription () const; + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. The dumped content will be only what has + /// been loaded or parsed up to this point at which this function + /// is called, so this is a good way to see what has been parsed + /// in a module. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext (Stream *s); + + + //------------------------------------------------------------------ + /// Find a symbol in the object file's symbol table. + /// + /// @param[in] name + /// The name of the symbol that we are looking for. + /// + /// @param[in] symbol_type + /// If set to eSymbolTypeAny, find a symbol of any type that + /// has a name that matches \a name. If set to any other valid + /// SymbolType enumeration value, then search only for + /// symbols that match \a symbol_type. + /// + /// @return + /// Returns a valid symbol pointer if a symbol was found, + /// NULL otherwise. + //------------------------------------------------------------------ + const Symbol * + FindFirstSymbolWithNameAndType (const ConstString &name, + lldb::SymbolType symbol_type = lldb::eSymbolTypeAny); + + size_t + FindSymbolsWithNameAndType (const ConstString &name, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list); + + size_t + FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list); + + //------------------------------------------------------------------ + /// Find a funciton symbols in the object file's symbol table. + /// + /// @param[in] name + /// The name of the symbol that we are looking for. + /// + /// @param[in] name_type_mask + /// A mask that has one or more bitwise OR'ed values from the + /// lldb::FunctionNameType enumeration type that indicate what + /// kind of names we are looking for. + /// + /// @param[out] sc_list + /// A list to append any matching symbol contexts to. + /// + /// @return + /// The number of symbol contexts that were added to \a sc_list + //------------------------------------------------------------------ + size_t + FindFunctionSymbols (const ConstString &name, + uint32_t name_type_mask, + 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. + //------------------------------------------------------------------ + size_t + FindCompileUnits (const FileSpec &path, + bool append, + SymbolContextList &sc_list); + + + //------------------------------------------------------------------ + /// Find functions by name. + /// + /// If the function is an inlined function, it will have a block, + /// representing the inlined function, and the function will be the + /// containing function. If it is not inlined, then the block will + /// be NULL. + /// + /// @param[in] name + /// The name of the compile unit we are looking for. + /// + /// @param[in] namespace_decl + /// If valid, a namespace to search in. + /// + /// @param[in] name_type_mask + /// A bit mask of 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 \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 + /// matches. + /// + /// @return + /// The number of matches added to \a sc_list. + //------------------------------------------------------------------ + size_t + FindFunctions (const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + uint32_t name_type_mask, + bool symbols_ok, + bool inlines_ok, + bool append, + SymbolContextList& sc_list); + + //------------------------------------------------------------------ + /// Find functions by name. + /// + /// If the function is an inlined function, it will have a block, + /// representing the inlined function, and the function will be the + /// containing function. If it is not inlined, then the block will + /// be NULL. + /// + /// @param[in] regex + /// A regular expression to use when matching the name. + /// + /// @param[in] append + /// 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 + /// matches. + /// + /// @return + /// The number of matches added to \a sc_list. + //------------------------------------------------------------------ + size_t + FindFunctions (const RegularExpression& regex, + bool symbols_ok, + bool inlines_ok, + bool append, + SymbolContextList& sc_list); + + //------------------------------------------------------------------ + /// Find global and static variables by name. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @param[in] namespace_decl + /// If valid, a namespace to search in. + /// + /// @param[in] append + /// If \b true, any matches will be appended to \a + /// variable_list, else matches replace the contents of + /// \a variable_list. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// @param[in] variable_list + /// A list of variables that gets the matches appended to (if + /// \a append it \b true), or replace (if \a append is \b false). + /// + /// @return + /// The number of matches added to \a variable_list. + //------------------------------------------------------------------ + size_t + FindGlobalVariables (const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + size_t max_matches, + VariableList& variable_list); + + //------------------------------------------------------------------ + /// Find global and static variables by regular exression. + /// + /// @param[in] regex + /// 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. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// @param[in] variable_list + /// A list of variables that gets the matches appended to (if + /// \a append it \b true), or replace (if \a append is \b false). + /// + /// @return + /// The number of matches added to \a variable_list. + //------------------------------------------------------------------ + size_t + FindGlobalVariables (const RegularExpression& regex, + bool append, + size_t max_matches, + VariableList& variable_list); + + //------------------------------------------------------------------ + /// Find types by name. + /// + /// Type lookups in modules go through the SymbolVendor (which will + /// use one or more SymbolFile subclasses). The SymbolFile needs to + /// be able to lookup types by basename and not the fully qualified + /// typename. This allows the type accelerator tables to stay small, + /// even with heavily templatized C++. The type search will then + /// narrow down the search results. If "exact_match" is true, then + /// the type search will only match exact type name matches. If + /// "exact_match" is false, the type will match as long as the base + /// typename matches and as long as any immediate containing + /// namespaces/class scopes that are specified match. So to search + /// for a type "d" in "b::c", the name "b::c::d" can be specified + /// and it will match any class/namespace "b" which contains a + /// class/namespace "c" which contains type "d". We do this to + /// allow users to not always have to specify complete scoping on + /// all expressions, but it also allows for exact matching when + /// required. + /// + /// @param[in] sc + /// A symbol context that scopes where to extract a type list + /// from. + /// + /// @param[in] type_name + /// The name of the type we are looking for that is a fully + /// or partially qualfieid type name. + /// + /// @param[in] exact_match + /// If \b true, \a type_name is fully qualifed and must match + /// exactly. If \b false, \a type_name is a partially qualfied + /// name where the leading namespaces or classes can be + /// omitted to make finding types that a user may type + /// easier. + /// + /// @param[out] type_list + /// A type list gets populated with any matches. + /// + /// @return + /// The number of matches added to \a type_list. + //------------------------------------------------------------------ + size_t + FindTypes (const SymbolContext& sc, + const ConstString &type_name, + bool exact_match, + size_t max_matches, + TypeList& types); + + lldb::TypeSP + FindFirstType (const SymbolContext& sc, + const ConstString &type_name, + bool exact_match); + + //------------------------------------------------------------------ + /// Find types by name that are in a namespace. This function is + /// used by the expression parser when searches need to happen in + /// an exact namespace scope. + /// + /// @param[in] sc + /// A symbol context that scopes where to extract a type list + /// from. + /// + /// @param[in] type_name + /// The name of a type within a namespace that should not include + /// any qualifying namespaces (just a type basename). + /// + /// @param[in] namespace_decl + /// The namespace declaration that this type must exist in. + /// + /// @param[out] type_list + /// A type list gets populated with any matches. + /// + /// @return + /// The number of matches added to \a type_list. + //------------------------------------------------------------------ + size_t + FindTypesInNamespace (const SymbolContext& sc, + const ConstString &type_name, + const ClangNamespaceDecl *namespace_decl, + size_t max_matches, + TypeList& type_list); + + //------------------------------------------------------------------ + /// Get const accessor for the module architecture. + /// + /// @return + /// A const reference to the architecture object. + //------------------------------------------------------------------ + const ArchSpec& + GetArchitecture () const; + + //------------------------------------------------------------------ + /// 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. + //------------------------------------------------------------------ + const FileSpec & + GetFileSpec () const + { + return m_file; + } + + //------------------------------------------------------------------ + /// 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. + //------------------------------------------------------------------ + const FileSpec & + GetPlatformFileSpec () const + { + if (m_platform_file) + return m_platform_file; + return m_file; + } + + void + SetPlatformFileSpec (const FileSpec &file) + { + m_platform_file = file; + } + + const FileSpec & + GetSymbolFileFileSpec () const + { + return m_symfile_spec; + } + + void + SetSymbolFileFileSpec (const FileSpec &file); + + const TimeValue & + GetModificationTime () const + { + return m_mod_time; + } + + const TimeValue & + GetObjectModificationTime () const + { + return m_object_mod_time; + } + + void + SetObjectModificationTime (const TimeValue &mod_time) + { + m_mod_time = mod_time; + } + + //------------------------------------------------------------------ + /// Tells whether this module is capable of being the main executable + /// for a process. + /// + /// @return + /// \b true if it is, \b false otherwise. + //------------------------------------------------------------------ + bool + IsExecutable (); + + //------------------------------------------------------------------ + /// Tells whether this module has been loaded in the target passed in. + /// This call doesn't distinguish between whether the module is loaded + /// by the dynamic loader, or by a "target module add" type call. + /// + /// @param[in] target + /// The target to check whether this is loaded in. + /// + /// @return + /// \b true if it is, \b false otherwise. + //------------------------------------------------------------------ + bool + IsLoadedInTarget (Target *target); + + bool + LoadScriptingResourceInTarget (Target *target, + Error& error, + Stream* feedback_stream = NULL); + + //------------------------------------------------------------------ + /// Get the number of compile units for this module. + /// + /// @return + /// The number of compile units that the symbol vendor plug-in + /// finds. + //------------------------------------------------------------------ + size_t + GetNumCompileUnits(); + + lldb::CompUnitSP + GetCompileUnitAtIndex (size_t idx); + + const ConstString & + GetObjectName() const; + + uint64_t + GetObjectOffset() const + { + return m_object_offset; + } + + //------------------------------------------------------------------ + /// Get the object file representation for the current architecture. + /// + /// If the object file has not been located or parsed yet, this + /// function will find the best ObjectFile plug-in that can parse + /// Module::m_file. + /// + /// @return + /// If Module::m_file does not exist, or no plug-in was found + /// that can parse the file, or the object file doesn't contain + /// the current architecture in Module::m_arch, NULL will be + /// returned, else a valid object file interface will be + /// returned. The returned pointer is owned by this object and + /// remains valid as long as the object is around. + //------------------------------------------------------------------ + virtual ObjectFile * + GetObjectFile (); + + //------------------------------------------------------------------ + /// Get the unified section list for the module. This is the section + /// list created by the module's object file and any debug info and + /// symbol files created by the symbol vendor. + /// + /// If the symbol vendor has not been loaded yet, this function + /// will return the section list for the object file. + /// + /// @return + /// Unified module section list. + //------------------------------------------------------------------ + virtual SectionList * + GetSectionList (); + + uint32_t + GetVersion (uint32_t *versions, uint32_t num_versions); + + // Load an object file from memory. + ObjectFile * + GetMemoryObjectFile (const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, + Error &error); + //------------------------------------------------------------------ + /// Get the symbol vendor interface for the current architecture. + /// + /// If the symbol vendor file has not been located yet, this + /// function will find the best SymbolVendor plug-in that can + /// use the current object file. + /// + /// @return + /// If this module does not have a valid object file, or no + /// plug-in can be found that can use the object file, NULL will + /// be returned, else a valid symbol vendor plug-in interface + /// will be returned. The returned pointer is owned by this + /// object and remains valid as long as the object is around. + //------------------------------------------------------------------ + virtual SymbolVendor* + GetSymbolVendor(bool can_create = true, + lldb_private::Stream *feedback_strm = NULL); + + //------------------------------------------------------------------ + /// Get accessor the type list for this module. + /// + /// @return + /// A valid type list pointer, or NULL if there is no valid + /// symbol vendor for this module. + //------------------------------------------------------------------ + TypeList* + GetTypeList (); + + //------------------------------------------------------------------ + /// Get a pointer to the UUID value contained in this object. + /// + /// If the executable image file doesn't not have a UUID value built + /// into the file format, an MD5 checksum of the entire file, or + /// slice of the file for the current architecture should be used. + /// + /// @return + /// A const pointer to the internal copy of the UUID value in + /// this module if this module has a valid UUID value, NULL + /// otherwise. + //------------------------------------------------------------------ + const lldb_private::UUID & + GetUUID (); + + //------------------------------------------------------------------ + /// A debugging function that will cause everything in a module to + /// be parsed. + /// + /// All compile units will be pasred, along with all globals and + /// static variables and all functions for those compile units. + /// All types, scopes, local variables, static variables, global + /// variables, and line tables will be parsed. This can be used + /// prior to dumping a module to see a complete list of the + /// resuling debug information that gets parsed, or as a debug + /// function to ensure that the module can consume all of the + /// debug data the symbol vendor provides. + //------------------------------------------------------------------ + void + ParseAllDebugSymbols(); + + bool + ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr); + + uint32_t + ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc); + + //------------------------------------------------------------------ + /// Resolve items in the symbol context for a given file and line. + /// + /// Tries to resolve \a file_path and \a line to a list of matching + /// symbol contexts. + /// + /// The line table entries contains addresses that can be used to + /// further resolve the values in each match: the function, block, + /// symbol. Care should be taken to minimize the amount of + /// information that is requested to only what is needed -- + /// typically the module, compile unit, line table and line table + /// entry are sufficient. + /// + /// @param[in] file_path + /// A path to a source file to match. If \a file_path does not + /// specify a directory, then this query will match all files + /// whose base filename matches. If \a file_path does specify + /// a directory, the fullpath to the file must match. + /// + /// @param[in] line + /// The source line to match, or zero if just the compile unit + /// should be resolved. + /// + /// @param[in] check_inlines + /// Check for inline file and line number matches. This option + /// should be used sparingly as it will cause all line tables + /// for every compile unit to be parsed and searched for + /// matching inline file entries. + /// + /// @param[in] resolve_scope + /// The scope that should be resolved (see + /// SymbolContext::Scope). + /// + /// @param[out] sc_list + /// A symbol context list that gets matching symbols contexts + /// appended to. + /// + /// @return + /// The number of matches that were added to \a sc_list. + /// + /// @see SymbolContext::Scope + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContextForFilePath (const char *file_path, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list); + + //------------------------------------------------------------------ + /// Resolve items in the symbol context for a given file and line. + /// + /// Tries to resolve \a file_spec and \a line to a list of matching + /// symbol contexts. + /// + /// The line table entries contains addresses that can be used to + /// further resolve the values in each match: the function, block, + /// symbol. Care should be taken to minimize the amount of + /// information that is requested to only what is needed -- + /// typically the module, compile unit, line table and line table + /// entry are sufficient. + /// + /// @param[in] file_spec + /// A file spec to a source file to match. If \a file_path does + /// not specify a directory, then this query will match all + /// files whose base filename matches. If \a file_path does + /// specify a directory, the fullpath to the file must match. + /// + /// @param[in] line + /// The source line to match, or zero if just the compile unit + /// should be resolved. + /// + /// @param[in] check_inlines + /// Check for inline file and line number matches. This option + /// should be used sparingly as it will cause all line tables + /// for every compile unit to be parsed and searched for + /// matching inline file entries. + /// + /// @param[in] resolve_scope + /// The scope that should be resolved (see + /// SymbolContext::Scope). + /// + /// @param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// + /// @return + /// A integer that contains SymbolContext::Scope bits set for + /// each item that was successfully resolved. + /// + /// @see SymbolContext::Scope + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list); + + + void + SetFileSpecAndObjectName (const FileSpec &file, + const ConstString &object_name); + + bool + GetIsDynamicLinkEditor () const + { + return m_is_dynamic_loader_module; + } + + void + SetIsDynamicLinkEditor (bool b) + { + m_is_dynamic_loader_module = b; + } + + ClangASTContext & + GetClangASTContext (); + + // Special error functions that can do printf style formatting that will prepend the message with + // something appropriate for this module (like the architecture, path and object name (if any)). + // This centralizes code so that everyone doesn't need to format their error and log messages on + // their own and keeps the output a bit more consistent. + void + LogMessage (Log *log, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + + void + LogMessageVerboseBacktrace (Log *log, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + + void + ReportWarning (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + void + ReportError (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + // Only report an error once when the module is first detected to be modified + // so we don't spam the console with many messages. + void + ReportErrorIfModifyDetected (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + //------------------------------------------------------------------ + // Return true if the file backing this module has changed since the + // module was originally created since we saved the intial file + // modification time when the module first gets created. + //------------------------------------------------------------------ + bool + FileHasChanged () const; + + //------------------------------------------------------------------ + // SymbolVendor, SymbolFile and ObjectFile member objects should + // lock the module mutex to avoid deadlocks. + //------------------------------------------------------------------ + Mutex & + GetMutex () const + { + return m_mutex; + } + + PathMappingList & + GetSourceMappingList () + { + return m_source_mappings; + } + + const PathMappingList & + GetSourceMappingList () const + { + return m_source_mappings; + } + + //------------------------------------------------------------------ + /// Finds a source file given a file spec using the module source + /// path remappings (if any). + /// + /// Tries to resolve \a orig_spec by checking the module source path + /// remappings. It makes sure the file exists, so this call can be + /// expensive if the remappings are on a network file system, so + /// use this function sparingly (not in a tight debug info parsing + /// loop). + /// + /// @param[in] orig_spec + /// The original source file path to try and remap. + /// + /// @param[out] new_spec + /// The newly remapped filespec that is guaranteed to exist. + /// + /// @return + /// /b true if \a orig_spec was successfully located and + /// \a new_spec is filled in with an existing file spec, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const; + + //------------------------------------------------------------------ + /// Remaps a source file given \a path into \a new_path. + /// + /// Remaps \a path if any source remappings match. This function + /// does NOT stat the file system so it can be used in tight loops + /// where debug info is being parsed. + /// + /// @param[in] path + /// The original source file path to try and remap. + /// + /// @param[out] new_path + /// The newly remapped filespec that is may or may not exist. + /// + /// @return + /// /b true if \a path was successfully located and \a new_path + /// is filled in with a new source path, \b false otherwise. + //------------------------------------------------------------------ + bool + RemapSourceFile (const char *path, std::string &new_path) const; + + + //------------------------------------------------------------------ + /// Prepare to do a function name lookup. + /// + /// Looking up functions by name can be a tricky thing. LLDB requires + /// that accelerator tables contain full names for functions as well + /// as function basenames which include functions, class methods and + /// class functions. When the user requests that an action use a + /// function by name, we are sometimes asked to automatically figure + /// out what a name could possibly map to. A user might request a + /// breakpoint be set on "count". If no options are supplied to limit + /// the scope of where to search for count, we will by default match + /// any function names named "count", all class and instance methods + /// named "count" (no matter what the namespace or contained context) + /// and any selectors named "count". If a user specifies "a::b" we + /// will search for the basename "b", and then prune the results that + /// don't match "a::b" (note that "c::a::b" and "d::e::a::b" will + /// match a query of "a::b". + /// + /// @param[in] name + /// The user supplied name to use in the lookup + /// + /// @param[in] name_type_mask + /// The mask of bits from lldb::FunctionNameType enumerations + /// that tell us what kind of name we are looking for. + /// + /// @param[out] lookup_name + /// The actual name that will be used when calling + /// SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols() + /// + /// @param[out] lookup_name_type_mask + /// The actual name mask that should be used in the calls to + /// SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols() + /// + /// @param[out] match_name_after_lookup + /// A boolean that indicates if we need to iterate through any + /// match results obtained from SymbolVendor::FindFunctions() or + /// Symtab::FindFunctionSymbols() to see if the name contains + /// \a name. For example if \a name is "a::b", this function will + /// return a \a lookup_name of "b", with \a match_name_after_lookup + /// set to true to indicate any matches will need to be checked + /// to make sure they contain \a name. + //------------------------------------------------------------------ + static void + PrepareForFunctionNameLookup (const ConstString &name, + uint32_t name_type_mask, + ConstString &lookup_name, + uint32_t &lookup_name_type_mask, + bool &match_name_after_lookup); + +protected: + //------------------------------------------------------------------ + // Member Variables + //------------------------------------------------------------------ + mutable Mutex m_mutex; ///< A mutex to keep this object happy in multi-threaded environments. + TimeValue m_mod_time; ///< The modification time for this module when it was created. + ArchSpec m_arch; ///< The architecture for this module. + lldb_private::UUID m_uuid; ///< Each module is assumed to have a unique identifier to help match it up to debug symbols. + FileSpec m_file; ///< The file representation on disk for this module (if there is one). + FileSpec m_platform_file;///< The path to the module on the platform on which it is being debugged + FileSpec m_symfile_spec; ///< If this path is valid, then this is the file that _will_ be used as the symbol file for this module + ConstString m_object_name; ///< The name an object within this module that is selected, or empty of the module is represented by \a m_file. + uint64_t m_object_offset; + TimeValue m_object_mod_time; + lldb::ObjectFileSP m_objfile_sp; ///< A shared pointer to the object file parser for this module as it may or may not be shared with the SymbolFile + std::unique_ptr<SymbolVendor> m_symfile_ap; ///< A pointer to the symbol vendor for this module. + ClangASTContext m_ast; ///< The AST context for this module. + PathMappingList m_source_mappings; ///< Module specific source remappings for when you have debug info for a module that doesn't match where the sources currently are + std::unique_ptr<lldb_private::SectionList> m_sections_ap; ///< Unified section list for module that is used by the ObjectFile and and ObjectFile instances for the debug info + + bool m_did_load_objfile:1, + m_did_load_symbol_vendor:1, + m_did_parse_uuid:1, + m_did_init_ast:1, + m_is_dynamic_loader_module:1; + mutable bool m_file_has_changed:1, + m_first_file_changed_log:1; /// See if the module was modified after it was initially opened. + + //------------------------------------------------------------------ + /// Resolve a file or load virtual address. + /// + /// Tries to resolve \a vm_addr as a file address (if \a + /// vm_addr_is_file_addr is true) or as a load address if \a + /// vm_addr_is_file_addr is false) in the symbol vendor. + /// \a resolve_scope indicates what clients wish to resolve + /// and can be used to limit the scope of what is parsed. + /// + /// @param[in] vm_addr + /// The load virtual address to resolve. + /// + /// @param[in] vm_addr_is_file_addr + /// If \b true, \a vm_addr is a file address, else \a vm_addr + /// if a load address. + /// + /// @param[in] resolve_scope + /// The scope that should be resolved (see + /// SymbolContext::Scope). + /// + /// @param[out] so_addr + /// The section offset based address that got resolved if + /// any bits are returned. + /// + /// @param[out] sc + // The symbol context that has objects filled in. Each bit + /// in the \a resolve_scope pertains to a member in the \a sc. + /// + /// @return + /// A integer that contains SymbolContext::Scope bits set for + /// each item that was successfully resolved. + /// + /// @see SymbolContext::Scope + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContextForAddress (lldb::addr_t vm_addr, + bool vm_addr_is_file_addr, + uint32_t resolve_scope, + Address& so_addr, + SymbolContext& sc); + + void + SymbolIndicesToSymbolContextList (Symtab *symtab, + std::vector<uint32_t> &symbol_indexes, + SymbolContextList &sc_list); + + bool + SetArchitecture (const ArchSpec &new_arch); + + SectionList * + GetUnifiedSectionList(); + + friend class ModuleList; + friend class ObjectFile; + friend class SymbolFile; + +private: + + size_t + FindTypes_Impl (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + size_t max_matches, + TypeList& types); + + + DISALLOW_COPY_AND_ASSIGN (Module); +}; + +} // namespace lldb_private + +#endif // liblldb_Module_h_ diff --git a/include/lldb/Core/ModuleChild.h b/include/lldb/Core/ModuleChild.h new file mode 100644 index 0000000..d2a6fb0 --- /dev/null +++ b/include/lldb/Core/ModuleChild.h @@ -0,0 +1,90 @@ +//===-- ModuleChild.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_ModuleChild_h_ +#define liblldb_ModuleChild_h_ + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ModuleChild ModuleChild.h "lldb/Core/ModuleChild.h" +/// @brief A mix in class that contains a pointer back to the module +/// that owns the object which inherits from it. +//---------------------------------------------------------------------- +class ModuleChild +{ +public: + //------------------------------------------------------------------ + /// Construct with owning module. + /// + /// @param[in] module + /// The module that owns the object that inherits from this + /// class. + //------------------------------------------------------------------ + ModuleChild (const lldb::ModuleSP &module_sp); + + //------------------------------------------------------------------ + /// Copy constructor. + /// + /// @param[in] rhs + /// A const ModuleChild class reference to copy. + //------------------------------------------------------------------ + ModuleChild (const ModuleChild& rhs); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~ModuleChild(); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// @param[in] rhs + /// A const ModuleChild class reference to copy. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const ModuleChild& + operator= (const ModuleChild& rhs); + + //------------------------------------------------------------------ + /// Get const accessor for the module pointer. + /// + /// @return + /// A const pointer to the module that owns the object that + /// inherits from this class. + //------------------------------------------------------------------ + lldb::ModuleSP + GetModule () const; + + //------------------------------------------------------------------ + /// Set accessor for the module pointer. + /// + /// @param[in] module + /// A new module that owns the object that inherits from this + /// class. + //------------------------------------------------------------------ + void + SetModule (const lldb::ModuleSP &module_sp); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + lldb::ModuleWP m_module_wp; ///< The Module that owns the object that inherits + ///< from this class. +}; + +} // namespace lldb_private + + +#endif // liblldb_ModuleChild_h_ diff --git a/include/lldb/Core/ModuleList.h b/include/lldb/Core/ModuleList.h new file mode 100644 index 0000000..1198e41 --- /dev/null +++ b/include/lldb/Core/ModuleList.h @@ -0,0 +1,556 @@ +//===-- ModuleList.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_ModuleList_h_ +#define liblldb_ModuleList_h_ + +#include <vector> +#include <list> + +#include "lldb/lldb-private.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ModuleList ModuleList.h "lldb/Core/ModuleList.h" +/// @brief A collection class for Module objects. +/// +/// Modules in the module collection class are stored as reference +/// counted shared pointers to Module objects. +//---------------------------------------------------------------------- +class ModuleList +{ +public: + + class Notifier + { + public: + virtual void + ModuleAdded (const ModuleList& module_list, const lldb::ModuleSP& module_sp) = 0; + virtual void + ModuleRemoved (const ModuleList& module_list, const lldb::ModuleSP& module_sp) = 0; + virtual void + ModuleUpdated (const ModuleList& module_list, const lldb::ModuleSP& old_module_sp, + const lldb::ModuleSP& new_module_sp) = 0; + virtual void + WillClearList (const ModuleList& module_list) = 0; + + virtual + ~Notifier () + {} + }; + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Creates an empty list of Module objects. + //------------------------------------------------------------------ + ModuleList (); + + //------------------------------------------------------------------ + /// Copy Constructor. + /// + /// Creates a new module list object with a copy of the modules from + /// \a rhs. + /// + /// @param[in] rhs + /// Another module list object. + //------------------------------------------------------------------ + ModuleList (const ModuleList& rhs); + + ModuleList (ModuleList::Notifier* notifier); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~ModuleList (); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// Copies the module list from \a rhs into this list. + /// + /// @param[in] rhs + /// Another module list object. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const ModuleList& + operator= (const ModuleList& rhs); + + //------------------------------------------------------------------ + /// Append a module to the module list. + /// + /// Appends the module to the collection. + /// + /// @param[in] module_sp + /// A shared pointer to a module to add to this collection. + //------------------------------------------------------------------ + void + Append (const lldb::ModuleSP &module_sp); + + //------------------------------------------------------------------ + /// Append a module to the module list and remove any equivalent + /// modules. Equivalent modules are ones whose file, platform file + /// and architecture matches. + /// + /// Replaces the module to the collection. + /// + /// @param[in] module_sp + /// A shared pointer to a module to replace in this collection. + //------------------------------------------------------------------ + void + ReplaceEquivalent (const lldb::ModuleSP &module_sp); + + bool + AppendIfNeeded (const lldb::ModuleSP &module_sp); + + void + Append (const ModuleList& module_list); + + bool + AppendIfNeeded (const ModuleList& module_list); + + bool + ReplaceModule (const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Clears the list of modules and releases a reference to each + /// module object and if the reference count goes to zero, the + /// module will be deleted. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Clears the list of modules and releases a reference to each + /// module object and if the reference count goes to zero, the + /// module will be deleted. Also relese all memory that might be + /// held by any collection classes (like std::vector) + //------------------------------------------------------------------ + void + Destroy(); + //------------------------------------------------------------------ + /// Dump the description of each module contained in this list. + /// + /// Dump the description of each module contained in this list to + /// the supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @see Module::Dump(Stream *) const + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + void + LogUUIDAndPaths (Log *log, const char *prefix_cstr); + + Mutex & + GetMutex () const + { + return m_modules_mutex; + } + + size_t + GetIndexForModule (const Module *module) const; + + //------------------------------------------------------------------ + /// Get the module shared pointer for the module at index \a idx. + /// + /// @param[in] idx + /// An index into this module collection. + /// + /// @return + /// A shared pointer to a Module which can contain NULL if + /// \a idx is out of range. + /// + /// @see ModuleList::GetSize() + //------------------------------------------------------------------ + lldb::ModuleSP + GetModuleAtIndex (size_t idx) const; + + //------------------------------------------------------------------ + /// Get the module shared pointer for the module at index \a idx without + /// acquiring the ModuleList mutex. This MUST already have been + /// acquired with ModuleList::GetMutex and locked for this call to be safe. + /// + /// @param[in] idx + /// An index into this module collection. + /// + /// @return + /// A shared pointer to a Module which can contain NULL if + /// \a idx is out of range. + /// + /// @see ModuleList::GetSize() + //------------------------------------------------------------------ + lldb::ModuleSP + GetModuleAtIndexUnlocked (size_t idx) const; + + //------------------------------------------------------------------ + /// Get the module pointer for the module at index \a idx. + /// + /// @param[in] idx + /// An index into this module collection. + /// + /// @return + /// A pointer to a Module which can by NULL if \a idx is out + /// of range. + /// + /// @see ModuleList::GetSize() + //------------------------------------------------------------------ + Module* + GetModulePointerAtIndex (size_t idx) const; + + //------------------------------------------------------------------ + /// Get the module pointer for the module at index \a idx without + /// acquiring the ModuleList mutex. This MUST already have been + /// acquired with ModuleList::GetMutex and locked for this call to be safe. + /// + /// @param[in] idx + /// An index into this module collection. + /// + /// @return + /// A pointer to a Module which can by NULL if \a idx is out + /// of range. + /// + /// @see ModuleList::GetSize() + //------------------------------------------------------------------ + Module* + GetModulePointerAtIndexUnlocked (size_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 compile unit 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. + //------------------------------------------------------------------ + size_t + FindCompileUnits (const FileSpec &path, + bool append, + SymbolContextList &sc_list) const; + + //------------------------------------------------------------------ + /// @see Module::FindFunctions () + //------------------------------------------------------------------ + size_t + FindFunctions (const ConstString &name, + uint32_t name_type_mask, + bool include_symbols, + bool include_inlines, + bool append, + SymbolContextList &sc_list) const; + + //------------------------------------------------------------------ + /// @see Module::FindFunctionSymbols () + //------------------------------------------------------------------ + size_t + FindFunctionSymbols (const ConstString &name, + uint32_t name_type_mask, + SymbolContextList& sc_list); + + //------------------------------------------------------------------ + /// Find global and static variables by name. + /// + /// @param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// @param[in] append + /// If \b true, any matches will be appended to \a + /// variable_list, else matches replace the contents of + /// \a variable_list. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// @param[in] variable_list + /// A list of variables that gets the matches appended to (if + /// \a append it \b true), or replace (if \a append is \b false). + /// + /// @return + /// The number of matches added to \a variable_list. + //------------------------------------------------------------------ + size_t + FindGlobalVariables (const ConstString &name, + bool append, + size_t max_matches, + VariableList& variable_list) const; + + //------------------------------------------------------------------ + /// Find global and static variables by regular exression. + /// + /// @param[in] regex + /// 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. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// @param[in] variable_list + /// A list of variables that gets the matches appended to (if + /// \a append it \b true), or replace (if \a append is \b false). + /// + /// @return + /// The number of matches added to \a variable_list. + //------------------------------------------------------------------ + size_t + FindGlobalVariables (const RegularExpression& regex, + bool append, + size_t max_matches, + VariableList& variable_list) const; + + //------------------------------------------------------------------ + /// Finds the first module whose file specification matches \a + /// file_spec. + /// + /// @param[in] file_spec_ptr + /// A file specification object to match against the Module's + /// file specifications. If \a file_spec does not have + /// directory information, matches will occur by matching only + /// the basename of any modules in this list. If this value is + /// NULL, then file specifications won't be compared when + /// searching for matching modules. + /// + /// @param[in] arch_ptr + /// The architecture to search for if non-NULL. If this value + /// is NULL no architecture matching will be performed. + /// + /// @param[in] uuid_ptr + /// The uuid to search for if non-NULL. If this value is NULL + /// no uuid matching will be performed. + /// + /// @param[in] object_name + /// An optional object name that must match as well. This value + /// can be NULL. + /// + /// @param[out] matching_module_list + /// A module list that gets filled in with any modules that + /// match the search criteria. + /// + /// @return + /// The number of matching modules found by the search. + //------------------------------------------------------------------ + size_t + FindModules (const ModuleSpec &module_spec, + ModuleList& matching_module_list) const; + + lldb::ModuleSP + FindModule (const Module *module_ptr) const; + + //------------------------------------------------------------------ + // Find a module by UUID + // + // The UUID value for a module is extracted from the ObjectFile and + // is the MD5 checksum, or a smarter object file equivalent, so + // finding modules by UUID values is very efficient and accurate. + //------------------------------------------------------------------ + lldb::ModuleSP + FindModule (const UUID &uuid) const; + + lldb::ModuleSP + FindFirstModule (const ModuleSpec &module_spec) const; + + size_t + FindSymbolsWithNameAndType (const ConstString &name, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list, + bool append = false) const; + + size_t + FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list, + bool append = false) const; + + //------------------------------------------------------------------ + /// Find types by name. + /// + /// @param[in] sc + /// A symbol context that scopes where to extract a type list + /// from. + /// + /// @param[in] name + /// The name of the type we are looking for. + /// + /// @param[in] append + /// If \b true, any matches will be appended to \a + /// variable_list, else matches replace the contents of + /// \a variable_list. + /// + /// @param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// @param[in] encoding + /// Limit the search to specific types, or get all types if + /// set to Type::invalid. + /// + /// @param[in] udt_name + /// If the encoding is a user defined type, specify the name + /// of the user defined type ("struct", "union", "class", etc). + /// + /// @param[out] type_list + /// A type list gets populated with any matches. + /// + /// @return + /// The number of matches added to \a type_list. + //------------------------------------------------------------------ + size_t + FindTypes (const SymbolContext& sc, + const ConstString &name, + bool name_is_fully_qualified, + size_t max_matches, + TypeList& types) const; + + bool + FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const; + + bool + Remove (const lldb::ModuleSP &module_sp); + + size_t + Remove (ModuleList &module_list); + + bool + RemoveIfOrphaned (const Module *module_ptr); + + size_t + RemoveOrphans (bool mandatory); + + bool + ResolveFileAddress (lldb::addr_t vm_addr, + Address& so_addr) const; + + //------------------------------------------------------------------ + /// @copydoc Module::ResolveSymbolContextForAddress (const Address &,uint32_t,SymbolContext&) + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContextForAddress (const Address& so_addr, + uint32_t resolve_scope, + SymbolContext& sc) const; + + //------------------------------------------------------------------ + /// @copydoc Module::ResolveSymbolContextForFilePath (const char *,uint32_t,bool,uint32_t,SymbolContextList&) + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContextForFilePath (const char *file_path, + uint32_t line, + bool check_inlines, + uint32_t resolve_scope, + SymbolContextList& sc_list) const; + + //------------------------------------------------------------------ + /// @copydoc Module::ResolveSymbolContextsForFileSpec (const FileSpec &,uint32_t,bool,uint32_t,SymbolContextList&) + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, + uint32_t line, + bool check_inlines, + uint32_t resolve_scope, + SymbolContextList& sc_list) const; + + //------------------------------------------------------------------ + /// Gets the size of the module list. + /// + /// @return + /// The number of modules in the module list. + //------------------------------------------------------------------ + size_t + GetSize () const; + + bool + LoadScriptingResourcesInTarget (Target *target, + std::list<Error>& errors, + Stream* feedback_stream = NULL, + bool continue_on_error = true); + + static bool + ModuleIsInCache (const Module *module_ptr); + + static Error + GetSharedModule (const ModuleSpec &module_spec, + lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + lldb::ModuleSP *old_module_sp_ptr, + bool *did_create_ptr, + bool always_create = false); + + static bool + RemoveSharedModule (lldb::ModuleSP &module_sp); + + static size_t + FindSharedModules (const ModuleSpec &module_spec, + ModuleList &matching_module_list); + + static size_t + RemoveOrphanSharedModules (bool mandatory); + + static bool + RemoveSharedModuleIfOrphaned (const Module *module_ptr); + +protected: + //------------------------------------------------------------------ + // Class typedefs. + //------------------------------------------------------------------ + typedef std::vector<lldb::ModuleSP> collection; ///< The module collection type. + + void + AppendImpl (const lldb::ModuleSP &module_sp, bool use_notifier = true); + + bool + RemoveImpl (const lldb::ModuleSP &module_sp, bool use_notifier = true); + + collection::iterator + RemoveImpl (collection::iterator pos, bool use_notifier = true); + + void + ClearImpl (bool use_notifier = true); + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + collection m_modules; ///< The collection of modules. + mutable Mutex m_modules_mutex; + + Notifier* m_notifier; + +}; + +} // namespace lldb_private + +#endif // liblldb_ModuleList_h_ diff --git a/include/lldb/Core/ModuleSpec.h b/include/lldb/Core/ModuleSpec.h new file mode 100644 index 0000000..10e1ea9 --- /dev/null +++ b/include/lldb/Core/ModuleSpec.h @@ -0,0 +1,594 @@ +//===-- ModuleSpec.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_ModuleSpec_h_ +#define liblldb_ModuleSpec_h_ + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/UUID.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Target/PathMappingList.h" + +namespace lldb_private { + +class ModuleSpec +{ +public: + ModuleSpec () : + m_file (), + m_platform_file (), + m_symbol_file (), + m_arch (), + m_uuid (), + m_object_name (), + m_object_offset (0), + m_object_mod_time (), + m_source_mappings () + { + } + + ModuleSpec (const FileSpec &file_spec) : + m_file (file_spec), + m_platform_file (), + m_symbol_file (), + m_arch (), + m_uuid (), + m_object_name (), + m_object_offset (0), + m_object_mod_time (), + m_source_mappings () + { + } + + ModuleSpec (const FileSpec &file_spec, const ArchSpec &arch) : + m_file (file_spec), + m_platform_file (), + m_symbol_file (), + m_arch (arch), + m_uuid (), + m_object_name (), + m_object_offset (0), + m_object_mod_time (), + m_source_mappings () + { + } + + ModuleSpec (const ModuleSpec &rhs) : + m_file (rhs.m_file), + m_platform_file (rhs.m_platform_file), + m_symbol_file (rhs.m_symbol_file), + m_arch (rhs.m_arch), + m_uuid (rhs.m_uuid), + m_object_name (rhs.m_object_name), + m_object_offset (rhs.m_object_offset), + m_object_mod_time (rhs.m_object_mod_time), + m_source_mappings (rhs.m_source_mappings) + { + } + + ModuleSpec & + operator = (const ModuleSpec &rhs) + { + if (this != &rhs) + { + m_file = rhs.m_file; + m_platform_file = rhs.m_platform_file; + m_symbol_file = rhs.m_symbol_file; + m_arch = rhs.m_arch; + m_uuid = rhs.m_uuid; + m_object_name = rhs.m_object_name; + m_object_offset = rhs.m_object_offset; + m_object_mod_time = rhs.m_object_mod_time; + m_source_mappings = rhs.m_source_mappings; + } + return *this; + } + + FileSpec * + GetFileSpecPtr () + { + if (m_file) + return &m_file; + return NULL; + } + + const FileSpec * + GetFileSpecPtr () const + { + if (m_file) + return &m_file; + return NULL; + } + + FileSpec & + GetFileSpec () + { + return m_file; + } + const FileSpec & + GetFileSpec () const + { + return m_file; + } + + FileSpec * + GetPlatformFileSpecPtr () + { + if (m_platform_file) + return &m_platform_file; + return NULL; + } + + const FileSpec * + GetPlatformFileSpecPtr () const + { + if (m_platform_file) + return &m_platform_file; + return NULL; + } + + FileSpec & + GetPlatformFileSpec () + { + return m_platform_file; + } + + const FileSpec & + GetPlatformFileSpec () const + { + return m_platform_file; + } + + FileSpec * + GetSymbolFileSpecPtr () + { + if (m_symbol_file) + return &m_symbol_file; + return NULL; + } + + const FileSpec * + GetSymbolFileSpecPtr () const + { + if (m_symbol_file) + return &m_symbol_file; + return NULL; + } + + FileSpec & + GetSymbolFileSpec () + { + return m_symbol_file; + } + + const FileSpec & + GetSymbolFileSpec () const + { + return m_symbol_file; + } + + + ArchSpec * + GetArchitecturePtr () + { + if (m_arch.IsValid()) + return &m_arch; + return NULL; + } + + const ArchSpec * + GetArchitecturePtr () const + { + if (m_arch.IsValid()) + return &m_arch; + return NULL; + } + + ArchSpec & + GetArchitecture () + { + return m_arch; + } + + const ArchSpec & + GetArchitecture () const + { + return m_arch; + } + + UUID * + GetUUIDPtr () + { + if (m_uuid.IsValid()) + return &m_uuid; + return NULL; + } + + const UUID * + GetUUIDPtr () const + { + if (m_uuid.IsValid()) + return &m_uuid; + return NULL; + } + + UUID & + GetUUID () + { + return m_uuid; + } + + const UUID & + GetUUID () const + { + return m_uuid; + } + + ConstString & + GetObjectName () + { + return m_object_name; + } + + const ConstString & + GetObjectName () const + { + return m_object_name; + } + + uint64_t + GetObjectOffset () const + { + return m_object_offset; + } + + void + SetObjectOffset (uint64_t object_offset) + { + m_object_offset = object_offset; + } + + TimeValue & + GetObjectModificationTime () + { + return m_object_mod_time; + } + + const TimeValue & + GetObjectModificationTime () const + { + return m_object_mod_time; + } + + PathMappingList & + GetSourceMappingList () const + { + return m_source_mappings; + } + + void + Clear () + { + m_file.Clear(); + m_platform_file.Clear(); + m_symbol_file.Clear(); + m_arch.Clear(); + m_uuid.Clear(); + m_object_name.Clear(); + m_object_offset = 0; + m_source_mappings.Clear(false); + m_object_mod_time.Clear(); + } + + + operator bool () const + { + if (m_file) + return true; + if (m_platform_file) + return true; + if (m_symbol_file) + return true; + if (m_arch.IsValid()) + return true; + if (m_uuid.IsValid()) + return true; + if (m_object_name) + return true; + if (m_object_mod_time.IsValid()) + return true; + return false; + } + + void + Dump (Stream &strm) + { + bool dumped_something = false; + if (m_file) + { + strm.PutCString("file = '"); + strm << m_file; + strm.PutCString("'"); + dumped_something = true; + } + if (m_platform_file) + { + if (dumped_something) + strm.PutCString(", "); + strm.PutCString("platform_file = '"); + strm << m_platform_file; + strm.PutCString("'"); + dumped_something = true; + } + if (m_symbol_file) + { + if (dumped_something) + strm.PutCString(", "); + strm.PutCString("symbol_file = '"); + strm << m_symbol_file; + strm.PutCString("'"); + dumped_something = true; + } + if (m_arch.IsValid()) + { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("arch = %s", m_arch.GetTriple().str().c_str()); + dumped_something = true; + } + if (m_uuid.IsValid()) + { + if (dumped_something) + strm.PutCString(", "); + strm.PutCString("uuid = "); + m_uuid.Dump(&strm); + dumped_something = true; + } + if (m_object_name) + { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object_name = %s", m_object_name.GetCString()); + dumped_something = true; + } + if (m_object_offset > 0) + { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object_offset = 0x%" PRIx64, m_object_offset); + dumped_something = true; + } + if (m_object_mod_time.IsValid()) + { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object_mod_time = 0x%" PRIx64, m_object_mod_time.GetAsSecondsSinceJan1_1970()); + dumped_something = true; + } + } + + bool + Matches (const ModuleSpec &match_module_spec, bool exact_arch_match) const + { + if (match_module_spec.GetUUIDPtr() && match_module_spec.GetUUID() != GetUUID()) + return false; + if (match_module_spec.GetObjectName() && match_module_spec.GetObjectName() != GetObjectName()) + return false; + if (match_module_spec.GetFileSpecPtr()) + { + const FileSpec &fspec = match_module_spec.GetFileSpec(); + if (!FileSpec::Equal(fspec, GetFileSpec(), fspec.GetDirectory().IsEmpty() == false)) + return false; + } + if (match_module_spec.GetPlatformFileSpecPtr()) + { + const FileSpec &fspec = match_module_spec.GetPlatformFileSpec(); + if (!FileSpec::Equal(fspec, GetPlatformFileSpec(), fspec.GetDirectory().IsEmpty() == false)) + return false; + + } + if (match_module_spec.GetSymbolFileSpecPtr()) + { + const FileSpec &fspec = match_module_spec.GetSymbolFileSpec(); + if (!FileSpec::Equal(fspec, GetSymbolFileSpec(), fspec.GetDirectory().IsEmpty() == false)) + return false; + + } + if (match_module_spec.GetArchitecturePtr()) + { + if (exact_arch_match) + { + if (!GetArchitecture().IsExactMatch(match_module_spec.GetArchitecture())) + return false; + } + else + { + if (!GetArchitecture().IsCompatibleMatch(match_module_spec.GetArchitecture())) + return false; + } + } + return true; + } + +protected: + FileSpec m_file; + FileSpec m_platform_file; + FileSpec m_symbol_file; + ArchSpec m_arch; + UUID m_uuid; + ConstString m_object_name; + uint64_t m_object_offset; + TimeValue m_object_mod_time; + mutable PathMappingList m_source_mappings; +}; + +class ModuleSpecList +{ +public: + ModuleSpecList () : + m_specs(), + m_mutex(Mutex::eMutexTypeRecursive) + { + } + + ModuleSpecList (const ModuleSpecList &rhs) : + m_specs(), + m_mutex(Mutex::eMutexTypeRecursive) + { + Mutex::Locker lhs_locker(m_mutex); + Mutex::Locker rhs_locker(rhs.m_mutex); + m_specs = rhs.m_specs; + } + + ~ModuleSpecList () + { + } + + ModuleSpecList & + operator = (const ModuleSpecList &rhs) + { + if (this != &rhs) + { + Mutex::Locker lhs_locker(m_mutex); + Mutex::Locker rhs_locker(rhs.m_mutex); + m_specs = rhs.m_specs; + } + return *this; + } + + size_t + GetSize() const + { + Mutex::Locker locker(m_mutex); + return m_specs.size(); + } + + void + Clear () + { + Mutex::Locker locker(m_mutex); + m_specs.clear(); + } + + void + Append (const ModuleSpec &spec) + { + Mutex::Locker locker(m_mutex); + m_specs.push_back (spec); + } + + void + Append (const ModuleSpecList &rhs) + { + Mutex::Locker lhs_locker(m_mutex); + Mutex::Locker rhs_locker(rhs.m_mutex); + m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end()); + } + + // The index "i" must be valid and this can't be used in + // multi-threaded code as no mutex lock is taken. + ModuleSpec & + GetModuleSpecRefAtIndex (size_t i) + { + return m_specs[i]; + } + bool + GetModuleSpecAtIndex (size_t i, ModuleSpec &module_spec) const + { + Mutex::Locker locker(m_mutex); + if (i < m_specs.size()) + { + module_spec = m_specs[i]; + return true; + } + module_spec.Clear(); + return false; + } + + + bool + FindMatchingModuleSpec (const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const + { + Mutex::Locker locker(m_mutex); + bool exact_arch_match = true; + for (auto spec: m_specs) + { + if (spec.Matches(module_spec, exact_arch_match)) + { + match_module_spec = spec; + return true; + } + } + + // If there was an architecture, retry with a compatible arch + if (module_spec.GetArchitecturePtr()) + { + exact_arch_match = false; + for (auto spec: m_specs) + { + if (spec.Matches(module_spec, exact_arch_match)) + { + match_module_spec = spec; + return true; + } + } + } + match_module_spec.Clear(); + return false; + } + + size_t + FindMatchingModuleSpecs (const ModuleSpec &module_spec, ModuleSpecList &matching_list) const + { + Mutex::Locker locker(m_mutex); + bool exact_arch_match = true; + const size_t initial_match_count = matching_list.GetSize(); + for (auto spec: m_specs) + { + if (spec.Matches(module_spec, exact_arch_match)) + matching_list.Append (spec); + } + + // If there was an architecture, retry with a compatible arch if no matches were found + if (module_spec.GetArchitecturePtr() && (initial_match_count == matching_list.GetSize())) + { + exact_arch_match = false; + for (auto spec: m_specs) + { + if (spec.Matches(module_spec, exact_arch_match)) + matching_list.Append (spec); + } + } + return matching_list.GetSize() - initial_match_count; + } + + void + Dump (Stream &strm) + { + Mutex::Locker locker(m_mutex); + uint32_t idx = 0; + for (auto spec: m_specs) + { + strm.Printf("[%u] ", idx); + spec.Dump (strm); + strm.EOL(); + ++idx; + } + } + +protected: + typedef std::vector<ModuleSpec> collection; ///< The module collection type. + collection m_specs; ///< The collection of modules. + mutable Mutex m_mutex; +}; + +} // namespace lldb_private + +#endif // liblldb_ModuleSpec_h_ diff --git a/include/lldb/Core/Opcode.h b/include/lldb/Core/Opcode.h new file mode 100644 index 0000000..c07193b --- /dev/null +++ b/include/lldb/Core/Opcode.h @@ -0,0 +1,270 @@ +//===-- Opcode.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_Opcode_h +#define lldb_Opcode_h + +// C Includes +#include <string.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" + +namespace lldb +{ + class SBInstruction; +} + +namespace lldb_private { + + class Opcode + { + public: + enum Type + { + eTypeInvalid, + eType8, + eType16, + eType16_2, // a 32-bit Thumb instruction, made up of two words + eType32, + eType64, + eTypeBytes + }; + + Opcode () : m_type (eTypeInvalid) + { + } + + Opcode (uint8_t inst) : m_type (eType8) + { + m_data.inst8 = inst; + } + + Opcode (uint16_t inst) : m_type (eType16) + { + m_data.inst16 = inst; + } + + Opcode (uint32_t inst) : m_type (eType32) + { + m_data.inst32 = inst; + } + + Opcode (uint64_t inst) : m_type (eType64) + { + m_data.inst64 = inst; + } + + Opcode (uint8_t *bytes, size_t length) + { + SetOpcodeBytes (bytes, length); + } + + void + Clear() + { + m_type = Opcode::eTypeInvalid; + } + Opcode::Type + GetType () const + { + return m_type; + } + + uint8_t + GetOpcode8 (uint8_t invalid_opcode = UINT8_MAX) const + { + switch (m_type) + { + case Opcode::eTypeInvalid: break; + case Opcode::eType8: return m_data.inst8; + case Opcode::eType16: break; + case Opcode::eType16_2: break; + case Opcode::eType32: break; + case Opcode::eType64: break; + case Opcode::eTypeBytes: break; + break; + } + return invalid_opcode; + } + + uint16_t + GetOpcode16 (uint16_t invalid_opcode = UINT16_MAX) const + { + switch (m_type) + { + case Opcode::eTypeInvalid: break; + case Opcode::eType8: return m_data.inst8; + case Opcode::eType16: return m_data.inst16; + case Opcode::eType16_2: break; + case Opcode::eType32: break; + case Opcode::eType64: break; + case Opcode::eTypeBytes: break; + } + return invalid_opcode; + } + + uint32_t + GetOpcode32 (uint32_t invalid_opcode = UINT32_MAX) const + { + switch (m_type) + { + case Opcode::eTypeInvalid: break; + case Opcode::eType8: return m_data.inst8; + case Opcode::eType16: return m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: return m_data.inst32; + case Opcode::eType64: break; + case Opcode::eTypeBytes: break; + } + return invalid_opcode; + } + + uint64_t + GetOpcode64 (uint64_t invalid_opcode = UINT64_MAX) const + { + switch (m_type) + { + case Opcode::eTypeInvalid: break; + case Opcode::eType8: return m_data.inst8; + case Opcode::eType16: return m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: return m_data.inst32; + case Opcode::eType64: return m_data.inst64; + case Opcode::eTypeBytes: break; + } + return invalid_opcode; + } + + void + SetOpcode8 (uint8_t inst) + { + m_type = eType8; + m_data.inst8 = inst; + } + + void + SetOpcode16 (uint16_t inst) + { + m_type = eType16; + m_data.inst16 = inst; + } + + void + SetOpcode16_2 (uint32_t inst) + { + m_type = eType16_2; + m_data.inst32 = inst; + } + + void + SetOpcode32 (uint32_t inst) + { + m_type = eType32; + m_data.inst32 = inst; + } + + void + SetOpcode64 (uint64_t inst) + { + m_type = eType64; + m_data.inst64 = inst; + } + + void + SetOpcodeBytes (const void *bytes, size_t length) + { + if (bytes && length > 0) + { + m_type = eTypeBytes; + m_data.inst.length = length; + assert (length < sizeof (m_data.inst.bytes)); + memcpy (m_data.inst.bytes, bytes, length); + } + else + { + m_type = eTypeInvalid; + m_data.inst.length = 0; + } + } + + int + Dump (Stream *s, uint32_t min_byte_width); + + const void * + GetOpcodeBytes () const + { + if (m_type == Opcode::eTypeBytes) + return m_data.inst.bytes; + return NULL; + } + + uint32_t + GetByteSize () const + { + switch (m_type) + { + case Opcode::eTypeInvalid: break; + case Opcode::eType8: return sizeof(m_data.inst8); + case Opcode::eType16: return sizeof(m_data.inst16); + case Opcode::eType16_2: // passthrough + case Opcode::eType32: return sizeof(m_data.inst32); + case Opcode::eType64: return sizeof(m_data.inst64); + case Opcode::eTypeBytes: return m_data.inst.length; + } + return 0; + } + + // Get the opcode exactly as it would be laid out in memory. + uint32_t + GetData (DataExtractor &data) const; + + protected: + + friend class lldb::SBInstruction; + + const void * + GetOpcodeDataBytes () const + { + switch (m_type) + { + case Opcode::eTypeInvalid: break; + case Opcode::eType8: return &m_data.inst8; + case Opcode::eType16: return &m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: return &m_data.inst32; + case Opcode::eType64: return &m_data.inst64; + case Opcode::eTypeBytes: return m_data.inst.bytes; + } + return NULL; + } + + lldb::ByteOrder + GetDataByteOrder () const; + + Opcode::Type m_type; + union + { + uint8_t inst8; + uint16_t inst16; + uint32_t inst32; + uint64_t inst64; + struct + { + uint8_t bytes[16]; // This must be big enough to handle any opcode for any supported target. + uint8_t length; + } inst; + } m_data; + }; + +} // namespace lldb_private + +#endif // lldb_Opcode_h diff --git a/include/lldb/Core/PluginInterface.h b/include/lldb/Core/PluginInterface.h new file mode 100644 index 0000000..19371ca --- /dev/null +++ b/include/lldb/Core/PluginInterface.h @@ -0,0 +1,37 @@ +//===-- PluginInterface.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_PluginInterface_h_ +#define liblldb_PluginInterface_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class PluginInterface +{ +public: + virtual + ~PluginInterface () {} + + virtual ConstString + GetPluginName() = 0; + + virtual uint32_t + GetPluginVersion() = 0; + +}; + +} // namespace lldb_private + +#endif // liblldb_PluginInterface_h_ diff --git a/include/lldb/Core/PluginManager.h b/include/lldb/Core/PluginManager.h new file mode 100644 index 0000000..91f8fbb --- /dev/null +++ b/include/lldb/Core/PluginManager.h @@ -0,0 +1,352 @@ +//===-- PluginManager.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_PluginManager_h_ +#define liblldb_PluginManager_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Host/FileSpec.h" + +namespace lldb_private { + +class PluginManager +{ +public: + static void + Initialize (); + + static void + Terminate (); + + //------------------------------------------------------------------ + // ABI + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + ABICreateInstance create_callback); + + static bool + UnregisterPlugin (ABICreateInstance create_callback); + + static ABICreateInstance + GetABICreateCallbackAtIndex (uint32_t idx); + + static ABICreateInstance + GetABICreateCallbackForPluginName (const ConstString &name); + + + //------------------------------------------------------------------ + // Disassembler + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + DisassemblerCreateInstance create_callback); + + static bool + UnregisterPlugin (DisassemblerCreateInstance create_callback); + + static DisassemblerCreateInstance + GetDisassemblerCreateCallbackAtIndex (uint32_t idx); + + static DisassemblerCreateInstance + GetDisassemblerCreateCallbackForPluginName (const ConstString &name); + + + //------------------------------------------------------------------ + // DynamicLoader + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + DynamicLoaderCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = NULL); + + static bool + UnregisterPlugin (DynamicLoaderCreateInstance create_callback); + + static DynamicLoaderCreateInstance + GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx); + + static DynamicLoaderCreateInstance + GetDynamicLoaderCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // EmulateInstruction + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + EmulateInstructionCreateInstance create_callback); + + static bool + UnregisterPlugin (EmulateInstructionCreateInstance create_callback); + + static EmulateInstructionCreateInstance + GetEmulateInstructionCreateCallbackAtIndex (uint32_t idx); + + static EmulateInstructionCreateInstance + GetEmulateInstructionCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // OperatingSystem + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + OperatingSystemCreateInstance create_callback); + + static bool + UnregisterPlugin (OperatingSystemCreateInstance create_callback); + + static OperatingSystemCreateInstance + GetOperatingSystemCreateCallbackAtIndex (uint32_t idx); + + static OperatingSystemCreateInstance + GetOperatingSystemCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // LanguageRuntime + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + LanguageRuntimeCreateInstance create_callback); + + static bool + UnregisterPlugin (LanguageRuntimeCreateInstance create_callback); + + static LanguageRuntimeCreateInstance + GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx); + + static LanguageRuntimeCreateInstance + GetLanguageRuntimeCreateCallbackForPluginName (const ConstString &name); + + + //------------------------------------------------------------------ + // ObjectFile + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + ObjectFileCreateInstance create_callback, + ObjectFileCreateMemoryInstance create_memory_callback, + ObjectFileGetModuleSpecifications get_module_specifications); + + static bool + UnregisterPlugin (ObjectFileCreateInstance create_callback); + + static ObjectFileCreateInstance + GetObjectFileCreateCallbackAtIndex (uint32_t idx); + + static ObjectFileCreateMemoryInstance + GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx); + + static ObjectFileGetModuleSpecifications + GetObjectFileGetModuleSpecificationsCallbackAtIndex (uint32_t idx); + + static ObjectFileCreateInstance + GetObjectFileCreateCallbackForPluginName (const ConstString &name); + + static ObjectFileCreateMemoryInstance + GetObjectFileCreateMemoryCallbackForPluginName (const ConstString &name); + + + //------------------------------------------------------------------ + // ObjectContainer + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications); + + static bool + UnregisterPlugin (ObjectContainerCreateInstance create_callback); + + static ObjectContainerCreateInstance + GetObjectContainerCreateCallbackAtIndex (uint32_t idx); + + static ObjectContainerCreateInstance + GetObjectContainerCreateCallbackForPluginName (const ConstString &name); + + static ObjectFileGetModuleSpecifications + GetObjectContainerGetModuleSpecificationsCallbackAtIndex (uint32_t idx); + + //------------------------------------------------------------------ + // LogChannel + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + LogChannelCreateInstance create_callback); + + static bool + UnregisterPlugin (LogChannelCreateInstance create_callback); + + static LogChannelCreateInstance + GetLogChannelCreateCallbackAtIndex (uint32_t idx); + + static LogChannelCreateInstance + GetLogChannelCreateCallbackForPluginName (const ConstString &name); + + static const char * + GetLogChannelCreateNameAtIndex (uint32_t idx); + + //------------------------------------------------------------------ + // Platform + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + PlatformCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = NULL); + + static bool + UnregisterPlugin (PlatformCreateInstance create_callback); + + static PlatformCreateInstance + GetPlatformCreateCallbackAtIndex (uint32_t idx); + + static PlatformCreateInstance + GetPlatformCreateCallbackForPluginName (const ConstString &name); + + static const char * + GetPlatformPluginNameAtIndex (uint32_t idx); + + static const char * + GetPlatformPluginDescriptionAtIndex (uint32_t idx); + + static size_t + AutoCompletePlatformName (const char *partial_name, + StringList &matches); + //------------------------------------------------------------------ + // Process + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + ProcessCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = NULL); + + static bool + UnregisterPlugin (ProcessCreateInstance create_callback); + + static ProcessCreateInstance + GetProcessCreateCallbackAtIndex (uint32_t idx); + + static ProcessCreateInstance + GetProcessCreateCallbackForPluginName (const ConstString &name); + + static const char * + GetProcessPluginNameAtIndex (uint32_t idx); + + static const char * + GetProcessPluginDescriptionAtIndex (uint32_t idx); + + //------------------------------------------------------------------ + // SymbolFile + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + SymbolFileCreateInstance create_callback); + + static bool + UnregisterPlugin (SymbolFileCreateInstance create_callback); + + static SymbolFileCreateInstance + GetSymbolFileCreateCallbackAtIndex (uint32_t idx); + + static SymbolFileCreateInstance + GetSymbolFileCreateCallbackForPluginName (const ConstString &name); + + + //------------------------------------------------------------------ + // SymbolVendor + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + SymbolVendorCreateInstance create_callback); + + static bool + UnregisterPlugin (SymbolVendorCreateInstance create_callback); + + static SymbolVendorCreateInstance + GetSymbolVendorCreateCallbackAtIndex (uint32_t idx); + + static SymbolVendorCreateInstance + GetSymbolVendorCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // UnwindAssembly + //------------------------------------------------------------------ + static bool + RegisterPlugin (const ConstString &name, + const char *description, + UnwindAssemblyCreateInstance create_callback); + + static bool + UnregisterPlugin (UnwindAssemblyCreateInstance create_callback); + + static UnwindAssemblyCreateInstance + GetUnwindAssemblyCreateCallbackAtIndex (uint32_t idx); + + static UnwindAssemblyCreateInstance + GetUnwindAssemblyCreateCallbackForPluginName (const ConstString &name); + + //------------------------------------------------------------------ + // Some plug-ins might register a DebuggerInitializeCallback + // callback when registering the plug-in. After a new Debugger + // instance is created, this DebuggerInitialize function will get + // called. This allows plug-ins to install Properties and do any + // other initialization that requires a debugger instance. + //------------------------------------------------------------------ + static void + DebuggerInitialize (Debugger &debugger); + + static lldb::OptionValuePropertiesSP + GetSettingForDynamicLoaderPlugin (Debugger &debugger, + const ConstString &setting_name); + + static bool + CreateSettingForDynamicLoaderPlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForPlatformPlugin (Debugger &debugger, + const ConstString &setting_name); + + static bool + CreateSettingForPlatformPlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForProcessPlugin (Debugger &debugger, + const ConstString &setting_name); + + static bool + CreateSettingForProcessPlugin (Debugger &debugger, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, + bool is_global_property); + +}; + + +} // namespace lldb_private + +#endif // liblldb_PluginManager_h_ diff --git a/include/lldb/Core/RangeMap.h b/include/lldb/Core/RangeMap.h new file mode 100644 index 0000000..ee42467 --- /dev/null +++ b/include/lldb/Core/RangeMap.h @@ -0,0 +1,1543 @@ +//===-- RangeMap.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_RangeMap_h_ +#define liblldb_RangeMap_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "llvm/ADT/SmallVector.h" + +// Uncomment to make sure all Range objects are sorted when needed +//#define ASSERT_RANGEMAP_ARE_SORTED + +namespace lldb_private { + + + //---------------------------------------------------------------------- + // Templatized classes for dealing with generic ranges and also + // collections of ranges, or collections of ranges that have associated + // data. + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + // A simple range class where you get to define the type of the range + // base "B", and the type used for the range byte size "S". + //---------------------------------------------------------------------- + template <typename B, typename S> + struct Range + { + typedef B BaseType; + typedef S SizeType; + + BaseType base; + SizeType size; + + Range () : + base (0), + size (0) + { + } + + Range (BaseType b, SizeType s) : + base (b), + size (s) + { + } + + void + Clear (BaseType b = 0) + { + base = b; + size = 0; + } + + // Set the start value for the range, and keep the same size + BaseType + GetRangeBase () const + { + return base; + } + + void + SetRangeBase (BaseType b) + { + base = b; + } + + void + Slide (BaseType slide) + { + base += slide; + } + + BaseType + GetRangeEnd () const + { + return base + size; + } + + void + SetRangeEnd (BaseType end) + { + if (end > base) + size = end - base; + else + size = 0; + } + + SizeType + GetByteSize () const + { + return size; + } + + void + SetByteSize (SizeType s) + { + size = s; + } + + bool + IsValid() const + { + return size > 0; + } + + bool + Contains (BaseType r) const + { + return (GetRangeBase() <= r) && (r < GetRangeEnd()); + } + + bool + ContainsEndInclusive (BaseType r) const + { + return (GetRangeBase() <= r) && (r <= GetRangeEnd()); + } + + bool + Contains (const Range& range) const + { + return Contains(range.GetRangeBase()) && ContainsEndInclusive(range.GetRangeEnd()); + } + + bool + Overlap (const Range &rhs) const + { + const BaseType lhs_base = this->GetRangeBase(); + const BaseType rhs_base = rhs.GetRangeBase(); + const BaseType lhs_end = this->GetRangeEnd(); + const BaseType rhs_end = rhs.GetRangeEnd(); + bool result = (lhs_base <= rhs_end) && (lhs_end >= rhs_base); + return result; + } + + bool + operator < (const Range &rhs) const + { + if (base == rhs.base) + return size < rhs.size; + return base < rhs.base; + } + + bool + operator == (const Range &rhs) const + { + return base == rhs.base && size == rhs.size; + } + + bool + operator != (const Range &rhs) const + { + return base != rhs.base || size != rhs.size; + } + }; + + //---------------------------------------------------------------------- + // A range array class where you get to define the type of the ranges + // that the collection contains. + //---------------------------------------------------------------------- + + template <typename B, typename S, unsigned N> + class RangeArray + { + public: + typedef B BaseType; + typedef S SizeType; + typedef Range<B,S> Entry; + typedef llvm::SmallVector<Entry, N> Collection; + + RangeArray () : + m_entries () + { + } + + ~RangeArray() + { + } + + void + Append (const Entry &entry) + { + m_entries.push_back (entry); + } + + bool + RemoveEntrtAtIndex (uint32_t idx) + { + if (idx < m_entries.size()) + { + m_entries.erase (m_entries.begin() + idx); + return true; + } + return false; + } + + void + Sort () + { + if (m_entries.size() > 1) + std::stable_sort (m_entries.begin(), m_entries.end()); + } + +#ifdef ASSERT_RANGEMAP_ARE_SORTED + bool + IsSorted () const + { + typename Collection::const_iterator pos, end, prev; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && *pos < *prev) + return false; + } + return true; + } +#endif + void + CombineConsecutiveRanges () + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + // Can't combine if ranges if we have zero or one range + if (m_entries.size() > 1) + { + // The list should be sorted prior to calling this function + typename Collection::iterator pos; + typename Collection::iterator end; + typename Collection::iterator prev; + bool can_combine = false; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->Overlap(*pos)) + { + can_combine = true; + break; + } + } + + // We we can combine at least one entry, then we make a new collection + // and populate it accordingly, and then swap it into place. + if (can_combine) + { + Collection minimal_ranges; + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->Overlap(*pos)) + minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd())); + else + minimal_ranges.push_back (*pos); + } + // Use the swap technique in case our new vector is much smaller. + // We must swap when using the STL because std::vector objects never + // release or reduce the memory once it has been allocated/reserved. + m_entries.swap (minimal_ranges); + } + } + } + + + BaseType + GetMinRangeBase (BaseType fail_value) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (m_entries.empty()) + return fail_value; + // m_entries must be sorted, so if we aren't empty, we grab the + // first range's base + return m_entries.front().GetRangeBase(); + } + + BaseType + GetMaxRangeEnd (BaseType fail_value) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (m_entries.empty()) + return fail_value; + // m_entries must be sorted, so if we aren't empty, we grab the + // last range's end + return m_entries.back().GetRangeEnd(); + } + + void + Slide (BaseType slide) + { + typename Collection::iterator pos, end; + for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos) + pos->Slide (slide); + } + + void + Clear () + { + m_entries.clear(); + } + + bool + IsEmpty () const + { + return m_entries.empty(); + } + + size_t + GetSize () const + { + return m_entries.size(); + } + + const Entry * + GetEntryAtIndex (size_t i) const + { + if (i<m_entries.size()) + return &m_entries[i]; + return NULL; + } + + // Clients must ensure that "i" is a valid index prior to calling this function + const Entry & + GetEntryRef (size_t i) const + { + return m_entries[i]; + } + + Entry * + Back() + { + if (m_entries.empty()) + return NULL; + return &m_entries.back(); + } + + const Entry * + Back() const + { + if (m_entries.empty()) + return NULL; + return &m_entries.back(); + } + + static bool + BaseLessThan (const Entry& lhs, const Entry& rhs) + { + return lhs.GetRangeBase() < rhs.GetRangeBase(); + } + + uint32_t + FindEntryIndexThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (!m_entries.empty()) + { + Entry entry (addr, 1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return std::distance (begin, pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + return std::distance (begin, pos); + } + } + return UINT32_MAX; + } + + const Entry * + FindEntryThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (!m_entries.empty()) + { + Entry entry (addr, 1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + { + return &(*pos); + } + } + } + return NULL; + } + + const Entry * + FindEntryThatContains (const Entry &range) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (!m_entries.empty()) + { + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan); + + if (pos != end && pos->Contains(range)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(range)) + { + return &(*pos); + } + } + } + return NULL; + } + + protected: + Collection m_entries; + }; + + template <typename B, typename S> + class RangeVector + { + public: + typedef B BaseType; + typedef S SizeType; + typedef Range<B,S> Entry; + typedef std::vector<Entry> Collection; + + RangeVector () : + m_entries () + { + } + + ~RangeVector() + { + } + + void + Append (const Entry &entry) + { + m_entries.push_back (entry); + } + + bool + RemoveEntrtAtIndex (uint32_t idx) + { + if (idx < m_entries.size()) + { + m_entries.erase (m_entries.begin() + idx); + return true; + } + return false; + } + + void + Sort () + { + if (m_entries.size() > 1) + std::stable_sort (m_entries.begin(), m_entries.end()); + } + +#ifdef ASSERT_RANGEMAP_ARE_SORTED + bool + IsSorted () const + { + typename Collection::const_iterator pos, end, prev; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && *pos < *prev) + return false; + } + return true; + } +#endif + void + CombineConsecutiveRanges () + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + // Can't combine if ranges if we have zero or one range + if (m_entries.size() > 1) + { + // The list should be sorted prior to calling this function + typename Collection::iterator pos; + typename Collection::iterator end; + typename Collection::iterator prev; + bool can_combine = false; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->Overlap(*pos)) + { + can_combine = true; + break; + } + } + + // We we can combine at least one entry, then we make a new collection + // and populate it accordingly, and then swap it into place. + if (can_combine) + { + Collection minimal_ranges; + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->Overlap(*pos)) + minimal_ranges.back().SetRangeEnd (std::max<BaseType>(prev->GetRangeEnd(), pos->GetRangeEnd())); + else + minimal_ranges.push_back (*pos); + } + // Use the swap technique in case our new vector is much smaller. + // We must swap when using the STL because std::vector objects never + // release or reduce the memory once it has been allocated/reserved. + m_entries.swap (minimal_ranges); + } + } + } + + + BaseType + GetMinRangeBase (BaseType fail_value) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (m_entries.empty()) + return fail_value; + // m_entries must be sorted, so if we aren't empty, we grab the + // first range's base + return m_entries.front().GetRangeBase(); + } + + BaseType + GetMaxRangeEnd (BaseType fail_value) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (m_entries.empty()) + return fail_value; + // m_entries must be sorted, so if we aren't empty, we grab the + // last range's end + return m_entries.back().GetRangeEnd(); + } + + void + Slide (BaseType slide) + { + typename Collection::iterator pos, end; + for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos) + pos->Slide (slide); + } + + void + Clear () + { + m_entries.clear(); + } + + void + Reserve (typename Collection::size_type size) + { + m_entries.resize (size); + } + + bool + IsEmpty () const + { + return m_entries.empty(); + } + + size_t + GetSize () const + { + return m_entries.size(); + } + + const Entry * + GetEntryAtIndex (size_t i) const + { + if (i<m_entries.size()) + return &m_entries[i]; + return NULL; + } + + // Clients must ensure that "i" is a valid index prior to calling this function + const Entry & + GetEntryRef (size_t i) const + { + return m_entries[i]; + } + + Entry * + Back() + { + if (m_entries.empty()) + return NULL; + return &m_entries.back(); + } + + const Entry * + Back() const + { + if (m_entries.empty()) + return NULL; + return &m_entries.back(); + } + + static bool + BaseLessThan (const Entry& lhs, const Entry& rhs) + { + return lhs.GetRangeBase() < rhs.GetRangeBase(); + } + + uint32_t + FindEntryIndexThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (!m_entries.empty()) + { + Entry entry (addr, 1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return std::distance (begin, pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + return std::distance (begin, pos); + } + } + return UINT32_MAX; + } + + const Entry * + FindEntryThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (!m_entries.empty()) + { + Entry entry (addr, 1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + { + return &(*pos); + } + } + } + return NULL; + } + + const Entry * + FindEntryThatContains (const Entry &range) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if (!m_entries.empty()) + { + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan); + + if (pos != end && pos->Contains(range)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(range)) + { + return &(*pos); + } + } + } + return NULL; + } + + protected: + Collection m_entries; + }; + + //---------------------------------------------------------------------- + // A simple range with data class where you get to define the type of + // the range base "B", the type used for the range byte size "S", and + // the type for the associated data "T". + //---------------------------------------------------------------------- + template <typename B, typename S, typename T> + struct RangeData : public Range<B,S> + { + typedef T DataType; + + DataType data; + + RangeData () : + Range<B,S> (), + data () + { + } + + RangeData (B base, S size) : + Range<B,S> (base, size), + data () + { + } + + RangeData (B base, S size, DataType d) : + Range<B,S> (base, size), + data (d) + { + } + + bool + operator < (const RangeData &rhs) const + { + if (this->base == rhs.base) + { + if (this->size == rhs.size) + return this->data < rhs.data; + else + return this->size < rhs.size; + } + return this->base < rhs.base; + } + + bool + operator == (const RangeData &rhs) const + { + return this->GetRangeBase() == rhs.GetRangeBase() && + this->GetByteSize() == rhs.GetByteSize() && + this->data == rhs.data; + } + + bool + operator != (const RangeData &rhs) const + { + return this->GetRangeBase() != rhs.GetRangeBase() || + this->GetByteSize() != rhs.GetByteSize() || + this->data != rhs.data; + } + }; + + template <typename B, typename S, typename T, unsigned N> + class RangeDataArray + { + public: + typedef RangeData<B,S,T> Entry; + typedef llvm::SmallVector<Entry, N> Collection; + + + RangeDataArray () + { + } + + ~RangeDataArray() + { + } + + void + Append (const Entry &entry) + { + m_entries.push_back (entry); + } + + void + Sort () + { + if (m_entries.size() > 1) + std::stable_sort (m_entries.begin(), m_entries.end()); + } + +#ifdef ASSERT_RANGEMAP_ARE_SORTED + bool + IsSorted () const + { + typename Collection::const_iterator pos, end, prev; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && *pos < *prev) + return false; + } + return true; + } +#endif + + void + CombineConsecutiveEntriesWithEqualData () + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + typename Collection::iterator pos; + typename Collection::iterator end; + typename Collection::iterator prev; + bool can_combine = false; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->data == pos->data) + { + can_combine = true; + break; + } + } + + // We we can combine at least one entry, then we make a new collection + // and populate it accordingly, and then swap it into place. + if (can_combine) + { + Collection minimal_ranges; + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->data == pos->data) + minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd()); + else + minimal_ranges.push_back (*pos); + } + // Use the swap technique in case our new vector is much smaller. + // We must swap when using the STL because std::vector objects never + // release or reduce the memory once it has been allocated/reserved. + m_entries.swap (minimal_ranges); + } + } + + void + Clear () + { + m_entries.clear(); + } + + bool + IsEmpty () const + { + return m_entries.empty(); + } + + size_t + GetSize () const + { + return m_entries.size(); + } + + const Entry * + GetEntryAtIndex (size_t i) const + { + if (i<m_entries.size()) + return &m_entries[i]; + return NULL; + } + + // Clients must ensure that "i" is a valid index prior to calling this function + const Entry & + GetEntryRef (size_t i) const + { + return m_entries[i]; + } + + static bool + BaseLessThan (const Entry& lhs, const Entry& rhs) + { + return lhs.GetRangeBase() < rhs.GetRangeBase(); + } + + uint32_t + FindEntryIndexThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + Entry entry (addr, 1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return std::distance (begin, pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + return std::distance (begin, pos); + } + } + return UINT32_MAX; + } + + Entry * + FindEntryThatContains (B addr) + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + Entry entry; + entry.SetRangeBase(addr); + entry.SetByteSize(1); + typename Collection::iterator begin = m_entries.begin(); + typename Collection::iterator end = m_entries.end(); + typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + { + return &(*pos); + } + } + } + return NULL; + } + const Entry * + FindEntryThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + Entry entry; + entry.SetRangeBase(addr); + entry.SetByteSize(1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + { + return &(*pos); + } + } + } + return NULL; + } + + const Entry * + FindEntryThatContains (const Entry &range) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan); + + if (pos != end && pos->Contains(range)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(range)) + { + return &(*pos); + } + } + } + return NULL; + } + + Entry * + Back() + { + if (!m_entries.empty()) + return &m_entries.back(); + return NULL; + } + + const Entry * + Back() const + { + if (!m_entries.empty()) + return &m_entries.back(); + return NULL; + } + + protected: + Collection m_entries; + }; + + // Same as RangeDataArray, but uses std::vector as to not + // require static storage of N items in the class itself + template <typename B, typename S, typename T> + class RangeDataVector + { + public: + typedef RangeData<B,S,T> Entry; + typedef std::vector<Entry> Collection; + + RangeDataVector () + { + } + + ~RangeDataVector() + { + } + + void + Append (const Entry &entry) + { + m_entries.push_back (entry); + } + + void + Sort () + { + if (m_entries.size() > 1) + std::stable_sort (m_entries.begin(), m_entries.end()); + } + +#ifdef ASSERT_RANGEMAP_ARE_SORTED + bool + IsSorted () const + { + typename Collection::const_iterator pos, end, prev; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && *pos < *prev) + return false; + } + return true; + } +#endif + + void + CombineConsecutiveEntriesWithEqualData () + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + typename Collection::iterator pos; + typename Collection::iterator end; + typename Collection::iterator prev; + bool can_combine = false; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->data == pos->data) + { + can_combine = true; + break; + } + } + + // We we can combine at least one entry, then we make a new collection + // and populate it accordingly, and then swap it into place. + if (can_combine) + { + Collection minimal_ranges; + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && prev->data == pos->data) + minimal_ranges.back().SetRangeEnd (pos->GetRangeEnd()); + else + minimal_ranges.push_back (*pos); + } + // Use the swap technique in case our new vector is much smaller. + // We must swap when using the STL because std::vector objects never + // release or reduce the memory once it has been allocated/reserved. + m_entries.swap (minimal_ranges); + } + } + + // Calculate the byte size of ranges with zero byte sizes by finding + // the next entry with a base address > the current base address + void + CalculateSizesOfZeroByteSizeRanges () + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + typename Collection::iterator pos; + typename Collection::iterator end; + typename Collection::iterator next; + for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos) + { + if (pos->GetByteSize() == 0) + { + // Watch out for multiple entries with same address and make sure + // we find an entry that is greater than the current base address + // before we use that for the size + auto curr_base = pos->GetRangeBase(); + for (next = pos + 1; next != end; ++next) + { + auto next_base = next->GetRangeBase(); + if (next_base > curr_base) + { + pos->SetByteSize (next_base - curr_base); + break; + } + } + } + } + + } + + void + Clear () + { + m_entries.clear(); + } + + void + Reserve (typename Collection::size_type size) + { + m_entries.resize (size); + } + + bool + IsEmpty () const + { + return m_entries.empty(); + } + + size_t + GetSize () const + { + return m_entries.size(); + } + + const Entry * + GetEntryAtIndex (size_t i) const + { + if (i<m_entries.size()) + return &m_entries[i]; + return NULL; + } + + // Clients must ensure that "i" is a valid index prior to calling this function + const Entry & + GetEntryRef (size_t i) const + { + return m_entries[i]; + } + + static bool + BaseLessThan (const Entry& lhs, const Entry& rhs) + { + return lhs.GetRangeBase() < rhs.GetRangeBase(); + } + + uint32_t + FindEntryIndexThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + Entry entry (addr, 1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return std::distance (begin, pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + return std::distance (begin, pos); + } + } + return UINT32_MAX; + } + + Entry * + FindEntryThatContains (B addr) + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + Entry entry; + entry.SetRangeBase(addr); + entry.SetByteSize(1); + typename Collection::iterator begin = m_entries.begin(); + typename Collection::iterator end = m_entries.end(); + typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + { + return &(*pos); + } + } + } + return NULL; + } + const Entry * + FindEntryThatContains (B addr) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + Entry entry; + entry.SetRangeBase(addr); + entry.SetByteSize(1); + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end && pos->Contains(addr)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(addr)) + { + return &(*pos); + } + } + } + return NULL; + } + + const Entry * + FindEntryThatContains (const Entry &range) const + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + typename Collection::const_iterator begin = m_entries.begin(); + typename Collection::const_iterator end = m_entries.end(); + typename Collection::const_iterator pos = std::lower_bound (begin, end, range, BaseLessThan); + + if (pos != end && pos->Contains(range)) + { + return &(*pos); + } + else if (pos != begin) + { + --pos; + if (pos->Contains(range)) + { + return &(*pos); + } + } + } + return NULL; + } + + Entry * + Back() + { + if (!m_entries.empty()) + return &m_entries.back(); + return NULL; + } + + const Entry * + Back() const + { + if (!m_entries.empty()) + return &m_entries.back(); + return NULL; + } + + protected: + Collection m_entries; + }; + + + //---------------------------------------------------------------------- + // A simple range with data class where you get to define the type of + // the range base "B", the type used for the range byte size "S", and + // the type for the associated data "T". + //---------------------------------------------------------------------- + template <typename B, typename T> + struct AddressData + { + typedef B BaseType; + typedef T DataType; + + BaseType addr; + DataType data; + + AddressData () : + addr (), + data () + { + } + + AddressData (B a, DataType d) : + addr (a), + data (d) + { + } + + bool + operator < (const AddressData &rhs) const + { + if (this->addr == rhs.addr) + return this->data < rhs.data; + return this->addr < rhs.addr; + } + + bool + operator == (const AddressData &rhs) const + { + return this->addr == rhs.addr && + this->data == rhs.data; + } + + bool + operator != (const AddressData &rhs) const + { + return this->addr != rhs.addr || + this->data == rhs.data; + } + }; + + + template <typename B, typename T, unsigned N> + class AddressDataArray + { + public: + typedef AddressData<B,T> Entry; + typedef llvm::SmallVector<Entry, N> Collection; + + + AddressDataArray () + { + } + + ~AddressDataArray() + { + } + + void + Append (const Entry &entry) + { + m_entries.push_back (entry); + } + + void + Sort () + { + if (m_entries.size() > 1) + std::stable_sort (m_entries.begin(), m_entries.end()); + } + +#ifdef ASSERT_RANGEMAP_ARE_SORTED + bool + IsSorted () const + { + typename Collection::const_iterator pos, end, prev; + // First we determine if we can combine any of the Entry objects so we + // don't end up allocating and making a new collection for no reason + for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) + { + if (prev != end && *pos < *prev) + return false; + } + return true; + } +#endif + + void + Clear () + { + m_entries.clear(); + } + + bool + IsEmpty () const + { + return m_entries.empty(); + } + + size_t + GetSize () const + { + return m_entries.size(); + } + + const Entry * + GetEntryAtIndex (size_t i) const + { + if (i<m_entries.size()) + return &m_entries[i]; + return NULL; + } + + // Clients must ensure that "i" is a valid index prior to calling this function + const Entry & + GetEntryRef (size_t i) const + { + return m_entries[i]; + } + + static bool + BaseLessThan (const Entry& lhs, const Entry& rhs) + { + return lhs.addr < rhs.addr; + } + + Entry * + FindEntry (B addr, bool exact_match_only) + { +#ifdef ASSERT_RANGEMAP_ARE_SORTED + assert (IsSorted()); +#endif + if ( !m_entries.empty() ) + { + Entry entry; + entry.addr = addr; + typename Collection::iterator begin = m_entries.begin(); + typename Collection::iterator end = m_entries.end(); + typename Collection::iterator pos = std::lower_bound (begin, end, entry, BaseLessThan); + + if (pos != end) + { + if (pos->addr == addr || !exact_match_only) + return &(*pos); + } + } + return NULL; + } + + const Entry * + FindNextEntry (const Entry *entry) + { + if (entry >= &*m_entries.begin() && entry + 1 < &*m_entries.end()) + return entry + 1; + return NULL; + } + + Entry * + Back() + { + if (!m_entries.empty()) + return &m_entries.back(); + return NULL; + } + + const Entry * + Back() const + { + if (!m_entries.empty()) + return &m_entries.back(); + return NULL; + } + + protected: + Collection m_entries; + }; + +} // namespace lldb_private + +#endif // liblldb_RangeMap_h_ diff --git a/include/lldb/Core/RegisterValue.h b/include/lldb/Core/RegisterValue.h new file mode 100644 index 0000000..cf29cea --- /dev/null +++ b/include/lldb/Core/RegisterValue.h @@ -0,0 +1,406 @@ +//===-- RegisterValue.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_RegisterValue_h +#define lldb_RegisterValue_h + +// C Includes +#include <string.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-private.h" +#include "lldb/Host/Endian.h" + +//#define ENABLE_128_BIT_SUPPORT 1 +namespace lldb_private { + + class RegisterValue + { + public: + enum + { + kMaxRegisterByteSize = 32u + }; + enum Type + { + eTypeInvalid, + eTypeUInt8, + eTypeUInt16, + eTypeUInt32, + eTypeUInt64, +#if defined (ENABLE_128_BIT_SUPPORT) + eTypeUInt128, +#endif + eTypeFloat, + eTypeDouble, + eTypeLongDouble, + eTypeBytes + }; + + RegisterValue () : + m_type (eTypeInvalid) + { + } + + explicit + RegisterValue (uint8_t inst) : + m_type (eTypeUInt8) + { + m_data.uint8 = inst; + } + + explicit + RegisterValue (uint16_t inst) : + m_type (eTypeUInt16) + { + m_data.uint16 = inst; + } + + explicit + RegisterValue (uint32_t inst) : + m_type (eTypeUInt32) + { + m_data.uint32 = inst; + } + + explicit + RegisterValue (uint64_t inst) : + m_type (eTypeUInt64) + { + m_data.uint64 = inst; + } + +#if defined (ENABLE_128_BIT_SUPPORT) + explicit + RegisterValue (__uint128_t inst) : + m_type (eTypeUInt128) + { + m_data.uint128 = inst; + } +#endif + explicit + RegisterValue (float value) : + m_type (eTypeFloat) + { + m_data.ieee_float = value; + } + + explicit + RegisterValue (double value) : + m_type (eTypeDouble) + { + m_data.ieee_double = value; + } + + explicit + RegisterValue (long double value) : + m_type (eTypeLongDouble) + { + m_data.ieee_long_double = value; + } + + explicit + RegisterValue (uint8_t *bytes, size_t length, lldb::ByteOrder byte_order) + { + SetBytes (bytes, length, byte_order); + } + + RegisterValue::Type + GetType () const + { + return m_type; + } + + bool + CopyValue (const RegisterValue &rhs); + + void + SetType (RegisterValue::Type type) + { + m_type = type; + } + + RegisterValue::Type + SetType (const RegisterInfo *reg_info); + + bool + GetData (DataExtractor &data) const; + + // Copy the register value from this object into a buffer in "dst" + // and obey the "dst_byte_order" when copying the data. Also watch out + // in case "dst_len" is longer or shorter than the register value + // described by "reg_info" and only copy the least significant bytes + // of the register value, or pad the destination with zeroes if the + // register byte size is shorter that "dst_len" (all while correctly + // abiding the "dst_byte_order"). Returns the number of bytes copied + // into "dst". + uint32_t + GetAsMemoryData (const RegisterInfo *reg_info, + void *dst, + uint32_t dst_len, + lldb::ByteOrder dst_byte_order, + Error &error) const; + + uint32_t + SetFromMemoryData (const RegisterInfo *reg_info, + const void *src, + uint32_t src_len, + lldb::ByteOrder src_byte_order, + Error &error); + + bool + GetScalarValue (Scalar &scalar) const; + + uint8_t + GetAsUInt8 (uint8_t fail_value = UINT8_MAX, bool *success_ptr = NULL) const + { + if (m_type == eTypeUInt8) + { + if (success_ptr) + *success_ptr = true; + return m_data.uint8; + } + if (success_ptr) + *success_ptr = true; + return fail_value; + } + + uint16_t + GetAsUInt16 (uint16_t fail_value = UINT16_MAX, bool *success_ptr = NULL) const; + + uint32_t + GetAsUInt32 (uint32_t fail_value = UINT32_MAX, bool *success_ptr = NULL) const; + + uint64_t + GetAsUInt64 (uint64_t fail_value = UINT64_MAX, bool *success_ptr = NULL) const; + +#if defined (ENABLE_128_BIT_SUPPORT) + __uint128_t + GetAsUInt128 (__uint128_t fail_value = ~((__uint128_t)0), bool *success_ptr = NULL) const; +#endif + + float + GetAsFloat (float fail_value = 0.0f, bool *success_ptr = NULL) const; + + double + GetAsDouble (double fail_value = 0.0, bool *success_ptr = NULL) const; + + long double + GetAsLongDouble (long double fail_value = 0.0, bool *success_ptr = NULL) const; + + void + SetValueToInvalid () + { + m_type = eTypeInvalid; + } + + bool + ClearBit (uint32_t bit); + + bool + SetBit (uint32_t bit); + + bool + operator == (const RegisterValue &rhs) const; + + bool + operator != (const RegisterValue &rhs) const; + + void + operator = (uint8_t uint) + { + m_type = eTypeUInt8; + m_data.uint8 = uint; + } + + void + operator = (uint16_t uint) + { + m_type = eTypeUInt16; + m_data.uint16 = uint; + } + + void + operator = (uint32_t uint) + { + m_type = eTypeUInt32; + m_data.uint32 = uint; + } + + void + operator = (uint64_t uint) + { + m_type = eTypeUInt64; + m_data.uint64 = uint; + } + +#if defined (ENABLE_128_BIT_SUPPORT) + void + operator = (__uint128_t uint) + { + m_type = eTypeUInt128; + m_data.uint128 = uint; + } +#endif + void + operator = (float f) + { + m_type = eTypeFloat; + m_data.ieee_float = f; + } + + void + operator = (double f) + { + m_type = eTypeDouble; + m_data.ieee_double = f; + } + + void + operator = (long double f) + { + m_type = eTypeLongDouble; + m_data.ieee_long_double = f; + } + + void + SetUInt8 (uint8_t uint) + { + m_type = eTypeUInt8; + m_data.uint8 = uint; + } + + void + SetUInt16 (uint16_t uint) + { + m_type = eTypeUInt16; + m_data.uint16 = uint; + } + + void + SetUInt32 (uint32_t uint, Type t = eTypeUInt32) + { + m_type = t; + m_data.uint32 = uint; + } + + void + SetUInt64 (uint64_t uint, Type t = eTypeUInt64) + { + m_type = t; + m_data.uint64 = uint; + } + +#if defined (ENABLE_128_BIT_SUPPORT) + void + SetUInt128 (__uint128_t uint) + { + m_type = eTypeUInt128; + m_data.uint128 = uint; + } +#endif + bool + SetUInt (uint64_t uint, uint32_t byte_size); + + void + SetFloat (float f) + { + m_type = eTypeFloat; + m_data.ieee_float = f; + } + + void + SetDouble (double f) + { + m_type = eTypeDouble; + m_data.ieee_double = f; + } + + void + SetLongDouble (long double f) + { + m_type = eTypeLongDouble; + m_data.ieee_long_double = f; + } + + void + SetBytes (const void *bytes, size_t length, lldb::ByteOrder byte_order); + + bool + SignExtend (uint32_t sign_bitpos); + + Error + SetValueFromCString (const RegisterInfo *reg_info, + const char *value_str); + + Error + SetValueFromData (const RegisterInfo *reg_info, + DataExtractor &data, + lldb::offset_t offset, + bool partial_data_ok); + + // The default value of 0 for reg_name_right_align_at means no alignment at all. + bool + Dump (Stream *s, + const RegisterInfo *reg_info, + bool prefix_with_name, + bool prefix_with_alt_name, + lldb::Format format, + uint32_t reg_name_right_align_at = 0) const; + + void * + GetBytes (); + + const void * + GetBytes () const; + + lldb::ByteOrder + GetByteOrder () const + { + if (m_type == eTypeBytes) + return m_data.buffer.byte_order; + return lldb::endian::InlHostByteOrder(); + } + + uint32_t + GetByteSize () const; + + void + Clear(); + + protected: + + RegisterValue::Type m_type; + union + { + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; +#if defined (ENABLE_128_BIT_SUPPORT) + __uint128_t uint128; +#endif + float ieee_float; + double ieee_double; + long double ieee_long_double; + struct + { + uint8_t bytes[kMaxRegisterByteSize]; // This must be big enough to hold any register for any supported target. + uint8_t length; + lldb::ByteOrder byte_order; + } buffer; + } m_data; + }; + +} // namespace lldb_private + +#endif // lldb_RegisterValue_h diff --git a/include/lldb/Core/RegularExpression.h b/include/lldb/Core/RegularExpression.h new file mode 100644 index 0000000..eeeb914 --- /dev/null +++ b/include/lldb/Core/RegularExpression.h @@ -0,0 +1,253 @@ +//===-- RegularExpression.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_DBRegex_h_ +#define liblldb_DBRegex_h_ +#if defined(__cplusplus) + +#include <regex.h> +#include <stdint.h> + +#include <string> +#include <vector> + +namespace llvm +{ + class StringRef; +} + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class RegularExpression RegularExpression.h "lldb/Core/RegularExpression.h" +/// @brief A C++ wrapper class for regex. +/// +/// This regular expression class wraps the posix regex functions +/// \c regcomp(), \c regerror(), \c regexec(), and \c regfree() from +/// the header file in \c /usr/include/regex\.h. +//---------------------------------------------------------------------- +class RegularExpression +{ +public: + class Match + { + public: + Match (uint32_t max_matches) : + m_matches () + { + if (max_matches > 0) + m_matches.resize(max_matches + 1); + } + + void + Clear() + { + const size_t num_matches = m_matches.size(); + regmatch_t invalid_match = { -1, -1 }; + for (size_t i=0; i<num_matches; ++i) + m_matches[i] = invalid_match; + } + + size_t + GetSize () const + { + return m_matches.size(); + } + + regmatch_t * + GetData () + { + if (m_matches.empty()) + return NULL; + return m_matches.data(); + } + + bool + GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const; + + bool + GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const; + + bool + GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const; + + protected: + + std::vector<regmatch_t> m_matches; ///< Where parenthesized subexpressions results are stored + }; + //------------------------------------------------------------------ + /// Default constructor. + /// + /// The default constructor that initializes the object state such + /// that it contains no compiled regular expression. + //------------------------------------------------------------------ + RegularExpression (); + + //------------------------------------------------------------------ + /// Constructor that takes a regulare expression with flags. + /// + /// Constructor that compiles \a re using \a flags and stores the + /// resulting compiled regular expression into this object. + /// + /// @param[in] re + /// A c string that represents the regular expression to + /// compile. + /// + /// @param[in] flags + /// Flags that are passed the the \c regcomp() function. + //------------------------------------------------------------------ + explicit + RegularExpression (const char* re, int flags); + + // This one uses flags = REG_EXTENDED. + explicit + RegularExpression (const char* re); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// Any previosuly compiled regular expression contained in this + /// object will be freed. + //------------------------------------------------------------------ + ~RegularExpression (); + + RegularExpression (const RegularExpression &rhs); + + const RegularExpression & operator=(const RegularExpression &rhs); + + //------------------------------------------------------------------ + /// Compile a regular expression. + /// + /// Compile a regular expression using the supplied regular + /// expression text and flags. The compied regular expression lives + /// in this object so that it can be readily used for regular + /// expression matches. Execute() can be called after the regular + /// expression is compiled. Any previosuly compiled regular + /// expression contained in this object will be freed. + /// + /// @param[in] re + /// A NULL terminated C string that represents the regular + /// expression to compile. + /// + /// @param[in] flags + /// Flags that are passed the the \c regcomp() function. + /// + /// @return + /// \b true if the regular expression compiles successfully, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + Compile (const char* re); + + bool + Compile (const char* re, int flags); + + //------------------------------------------------------------------ + /// Executes a regular expression. + /// + /// Execute a regular expression match using the compiled regular + /// expression that is already in this object against the match + /// string \a s. If any parens are used for regular expression + /// matches \a match_count should indicate the number of regmatch_t + /// values that are present in \a match_ptr. The regular expression + /// will be executed using the \a execute_flags + /// + /// @param[in] string + /// The string to match against the compile regular expression. + /// + /// @param[in] match + /// A pointer to a RegularExpression::Match structure that was + /// properly initialized with the desired number of maximum + /// matches, or NULL if no parenthesized matching is needed. + /// + /// @param[in] execute_flags + /// Flags to pass to the \c regexec() function. + /// + /// @return + /// \b true if \a string matches the compiled regular + /// expression, \b false otherwise. + //------------------------------------------------------------------ + bool + Execute (const char* string, Match *match = NULL, int execute_flags = 0) const; + + size_t + GetErrorAsCString (char *err_str, size_t err_str_max_len) const; + + //------------------------------------------------------------------ + /// Free the compiled regular expression. + /// + /// If this object contains a valid compiled regular expression, + /// this function will free any resources it was consuming. + //------------------------------------------------------------------ + void + Free (); + + //------------------------------------------------------------------ + /// Access the regular expression text. + /// + /// Returns the text that was used to compile the current regular + /// expression. + /// + /// @return + /// The NULL terminated C string that was used to compile the + /// current regular expression + //------------------------------------------------------------------ + const char* + GetText () const; + + int + GetCompileFlags () const + { + return m_compile_flags; + } + + //------------------------------------------------------------------ + /// Test if valid. + /// + /// Test if this object contains a valid regular expression. + /// + /// @return + /// \b true if the regular expression compiled and is ready + /// for execution, \b false otherwise. + //------------------------------------------------------------------ + bool + IsValid () const; + + void + Clear () + { + Free(); + m_re.clear(); + m_compile_flags = 0; + m_comp_err = 1; + } + + int + GetErrorCode() const + { + return m_comp_err; + } + + bool + operator < (const RegularExpression& rhs) const; + +private: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + std::string m_re; ///< A copy of the original regular expression text + int m_comp_err; ///< Error code for the regular expression compilation + regex_t m_preg; ///< The compiled regular expression + int m_compile_flags; ///< Stores the flags from the last compile. +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_DBRegex_h_ diff --git a/include/lldb/Core/STLUtils.h b/include/lldb/Core/STLUtils.h new file mode 100644 index 0000000..9321e05 --- /dev/null +++ b/include/lldb/Core/STLUtils.h @@ -0,0 +1,94 @@ +//===-- STLUtils.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_STLUtils_h_ +#define liblldb_STLUtils_h_ +#if defined(__cplusplus) + +#include <string.h> + +#include <map> +#include <ostream> +#include <vector> + +//---------------------------------------------------------------------- +// C string less than compare function object +//---------------------------------------------------------------------- +struct CStringCompareFunctionObject +{ + bool operator() (const char* s1, const char* s2) const + { + return strcmp(s1, s2) < 0; + } +}; + + +//---------------------------------------------------------------------- +// C string equality function object (binary predicate). +//---------------------------------------------------------------------- +struct CStringEqualBinaryPredicate +{ + bool operator()(const char* s1, const char* s2) const + { + return strcmp(s1, s2) == 0; + } +}; + + +//---------------------------------------------------------------------- +// Templated type for finding an entry in a std::map<F,S> whose value +// is equal to something +//---------------------------------------------------------------------- +template <class F, class S> +class ValueEquals +{ +private: + S second_value; + +public: + ValueEquals (const S& val) : second_value(val) + {} + // Compare the second item + bool operator() (std::pair<const F, S> elem) + { + return elem.second == second_value; + } +}; + +template <class T> +inline void PrintAllCollectionElements (std::ostream &s, const T& coll, const char* header_cstr=NULL, const char* separator_cstr=" ") +{ + typename T::const_iterator pos; + + if (header_cstr) + s << header_cstr; + for (pos=coll.begin(); pos!=coll.end(); ++pos) { + s << *pos << separator_cstr; + } + s << std::endl; +} + +// The function object below can be used to delete a STL container that +// contains C++ object pointers. +// +// Usage: std::for_each(vector.begin(), vector.end(), for_each_delete()); + +struct for_each_cplusplus_delete +{ + template <typename T> + void operator()(T *ptr){ delete ptr;} +}; + +typedef std::vector<std::string> STLStringArray; +typedef std::vector<const char *> CStringArray; + + + +#endif // #if defined(__cplusplus) +#endif // liblldb_STLUtils_h_ diff --git a/include/lldb/Core/Scalar.h b/include/lldb/Core/Scalar.h new file mode 100644 index 0000000..821a0fb --- /dev/null +++ b/include/lldb/Core/Scalar.h @@ -0,0 +1,341 @@ +//===-- Scalar.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_Scalar_h_ +#define liblldb_Scalar_h_ + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A class designed to hold onto values and their corresponding types. +// Operators are defined and Scalar objects will correctly promote +// their types and values before performing these operations. Type +// promotion currently follows the ANSI C type promotion rules. +//---------------------------------------------------------------------- +class Scalar +{ +public: + enum Type + { + e_void = 0, + e_sint, + e_uint, + e_slong, + e_ulong, + e_slonglong, + e_ulonglong, + e_float, + e_double, + e_long_double + }; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Scalar(); + Scalar(int v) : m_type(e_sint), m_data() { m_data.sint = v; } + Scalar(unsigned int v) : m_type(e_uint), m_data() { m_data.uint = v; } + Scalar(long v) : m_type(e_slong), m_data() { m_data.slong = v; } + Scalar(unsigned long v) : m_type(e_ulong), m_data() { m_data.ulong = v; } + Scalar(long long v) : m_type(e_slonglong), m_data() { m_data.slonglong = v; } + Scalar(unsigned long long v): m_type(e_ulonglong), m_data() { m_data.ulonglong = v; } + Scalar(float v) : m_type(e_float), m_data() { m_data.flt = v; } + Scalar(double v) : m_type(e_double), m_data() { m_data.dbl = v; } + Scalar(long double v) : m_type(e_long_double), m_data() { m_data.ldbl = v; } + Scalar(const Scalar& rhs); + //Scalar(const RegisterValue& reg_value); + virtual ~Scalar(); + + bool + SignExtend (uint32_t bit_pos); + + bool + ExtractBitfield (uint32_t bit_size, + uint32_t bit_offset); + + size_t + GetByteSize() const; + + static size_t + GetMaxByteSize() + { + return sizeof(ValueData); + } + + bool + GetData (DataExtractor &data, size_t limit_byte_size = UINT32_MAX) const; + + size_t + GetAsMemoryData (void *dst, + size_t dst_len, + lldb::ByteOrder dst_byte_order, + Error &error) const; + + bool + IsZero() const; + + void + Clear() { m_type = e_void; m_data.ulonglong = 0; } + + const char * + GetTypeAsCString() const; + + void + GetValue (Stream *s, bool show_type) const; + + bool + IsValid() const + { + return (m_type >= e_sint) && (m_type <= e_long_double); + } + + bool + Promote(Scalar::Type type); + + bool + Cast (Scalar::Type type); + + bool + MakeSigned (); + + static const char * + GetValueTypeAsCString (Scalar::Type value_type); + + static Scalar::Type + GetValueTypeForSignedIntegerWithByteSize (size_t byte_size); + + static Scalar::Type + GetValueTypeForUnsignedIntegerWithByteSize (size_t byte_size); + + static Scalar::Type + GetValueTypeForFloatWithByteSize (size_t byte_size); + + //---------------------------------------------------------------------- + // All operators can benefits from the implicit conversions that will + // happen automagically by the compiler, so no temporary objects will + // need to be created. As a result, we currently don't need a variety of + // overloaded set value accessors. + //---------------------------------------------------------------------- + Scalar& operator= (const int i); + Scalar& operator= (unsigned int v); + Scalar& operator= (long v); + Scalar& operator= (unsigned long v); + Scalar& operator= (long long v); + Scalar& operator= (unsigned long long v); + Scalar& operator= (float v); + Scalar& operator= (double v); + Scalar& operator= (long double v); + Scalar& operator= (const Scalar& rhs); // Assignment operator + Scalar& operator+= (const Scalar& rhs); + Scalar& operator<<= (const Scalar& rhs); // Shift left + Scalar& operator>>= (const Scalar& rhs); // Shift right (arithmetic) + Scalar& operator&= (const Scalar& rhs); + + //---------------------------------------------------------------------- + // Shifts the current value to the right without maintaining the current + // sign of the value (if it is signed). + //---------------------------------------------------------------------- + bool + ShiftRightLogical(const Scalar& rhs); // Returns true on success + + //---------------------------------------------------------------------- + // Takes the absolute value of the current value if it is signed, else + // the value remains unchanged. + // Returns false if the contained value has a void type. + //---------------------------------------------------------------------- + bool + AbsoluteValue(); // Returns true on success + //---------------------------------------------------------------------- + // Negates the current value (even for unsigned values). + // Returns false if the contained value has a void type. + //---------------------------------------------------------------------- + bool + UnaryNegate(); // Returns true on success + //---------------------------------------------------------------------- + // Inverts all bits in the current value as long as it isn't void or + // a float/double/long double type. + // Returns false if the contained value has a void/float/double/long + // double type, else the value is inverted and true is returned. + //---------------------------------------------------------------------- + bool + OnesComplement(); // Returns true on success + + //---------------------------------------------------------------------- + // Access the type of the current value. + //---------------------------------------------------------------------- + Scalar::Type + GetType() const { return m_type; } + + //---------------------------------------------------------------------- + // Returns a casted value of the current contained data without + // modifying the current value. FAIL_VALUE will be returned if the type + // of the value is void or invalid. + //---------------------------------------------------------------------- + int + SInt(int fail_value = 0) const; + + // Return the raw unsigned integer without any casting or conversion + unsigned int + RawUInt () const; + + // Return the raw unsigned long without any casting or conversion + unsigned long + RawULong () const; + + // Return the raw unsigned long long without any casting or conversion + unsigned long long + RawULongLong () const; + + unsigned int + UInt(unsigned int fail_value = 0) const; + + long + SLong(long fail_value = 0) const; + + unsigned long + ULong(unsigned long fail_value = 0) const; + + long long + SLongLong(long long fail_value = 0) const; + + unsigned long long + ULongLong(unsigned long long fail_value = 0) const; + + float + Float(float fail_value = 0.0f) const; + + double + Double(double fail_value = 0.0) const; + + long double + LongDouble(long double fail_value = 0.0) const; + + uint64_t + GetRawBits64 (uint64_t fail_value) const; + + Error + SetValueFromCString (const char *s, lldb::Encoding encoding, size_t byte_size); + + Error + SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t byte_size); + + static bool + UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size) + { + if (total_byte_size > 8) + return false; + + if (total_byte_size == 8) + return true; + + const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; + return uval64 <= max; + } + + static bool + SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size) + { + if (total_byte_size > 8) + return false; + + if (total_byte_size == 8) + return true; + + const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; + const int64_t min = ~(max); + return min <= sval64 && sval64 <= max; + } + +protected: + typedef int sint_t; + typedef unsigned int uint_t; + typedef long slong_t; + typedef unsigned long ulong_t; + typedef long long slonglong_t; + typedef unsigned long long ulonglong_t; + typedef float float_t; + typedef double double_t; + typedef long double long_double_t; + + union ValueData + { + int sint; + unsigned int uint; + long slong; + unsigned long ulong; + long long slonglong; + unsigned long long ulonglong; + float flt; + double dbl; + long double ldbl; + }; + + //------------------------------------------------------------------ + // Classes that inherit from Scalar can see and modify these + //------------------------------------------------------------------ + Scalar::Type m_type; + ValueData m_data; + +private: + friend const Scalar operator+ (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator- (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator/ (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator* (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator& (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator| (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator% (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator^ (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator<< (const Scalar& lhs, const Scalar& rhs); + friend const Scalar operator>> (const Scalar& lhs, const Scalar& rhs); + friend bool operator== (const Scalar& lhs, const Scalar& rhs); + friend bool operator!= (const Scalar& lhs, const Scalar& rhs); + friend bool operator< (const Scalar& lhs, const Scalar& rhs); + friend bool operator<= (const Scalar& lhs, const Scalar& rhs); + friend bool operator> (const Scalar& lhs, const Scalar& rhs); + friend bool operator>= (const Scalar& lhs, const Scalar& rhs); + +}; + +//---------------------------------------------------------------------- +// Split out the operators into a format where the compiler will be able +// to implicitly convert numbers into Scalar objects. +// +// This allows code like: +// Scalar two(2); +// Scalar four = two * 2; +// Scalar eight = 2 * four; // This would cause an error if the +// // operator* was implemented as a +// // member function. +// SEE: +// Item 19 of "Effective C++ Second Edition" by Scott Meyers +// Differentiate among members functions, non-member functions, and +// friend functions +//---------------------------------------------------------------------- +const Scalar operator+ (const Scalar& lhs, const Scalar& rhs); +const Scalar operator- (const Scalar& lhs, const Scalar& rhs); +const Scalar operator/ (const Scalar& lhs, const Scalar& rhs); +const Scalar operator* (const Scalar& lhs, const Scalar& rhs); +const Scalar operator& (const Scalar& lhs, const Scalar& rhs); +const Scalar operator| (const Scalar& lhs, const Scalar& rhs); +const Scalar operator% (const Scalar& lhs, const Scalar& rhs); +const Scalar operator^ (const Scalar& lhs, const Scalar& rhs); +const Scalar operator<< (const Scalar& lhs, const Scalar& rhs); +const Scalar operator>> (const Scalar& lhs, const Scalar& rhs); +bool operator== (const Scalar& lhs, const Scalar& rhs); +bool operator!= (const Scalar& lhs, const Scalar& rhs); +bool operator< (const Scalar& lhs, const Scalar& rhs); +bool operator<= (const Scalar& lhs, const Scalar& rhs); +bool operator> (const Scalar& lhs, const Scalar& rhs); +bool operator>= (const Scalar& lhs, const Scalar& rhs); + +} // namespace lldb_private + +#endif // liblldb_Scalar_h_ diff --git a/include/lldb/Core/SearchFilter.h b/include/lldb/Core/SearchFilter.h new file mode 100644 index 0000000..57f1b9c --- /dev/null +++ b/include/lldb/Core/SearchFilter.h @@ -0,0 +1,447 @@ +//===-- SearchFilter.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_SearchFilter_h_ +#define liblldb_SearchFilter_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/FileSpecList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Searcher SearchFilter.h "lldb/Core/SearchFilter.h" +/// @brief Class that is driven by the SearchFilter to search the +/// SymbolContext space of the target program. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// Provides the callback and search depth for the SearchFilter search. +//---------------------------------------------------------------------- + +class Searcher +{ +public: + typedef enum { + eCallbackReturnStop = 0, // Stop the iteration + eCallbackReturnContinue, // Continue the iteration + eCallbackReturnPop // Pop one level up and continue iterating + } CallbackReturn; + + typedef enum { + eDepthTarget, + eDepthModule, + eDepthCompUnit, + eDepthFunction, + eDepthBlock, + eDepthAddress + } Depth; + + Searcher (); + + virtual ~Searcher (); + + virtual CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete) = 0; + + virtual Depth + GetDepth () = 0; + + //------------------------------------------------------------------ + /// Prints a canonical description for the searcher to the stream \a s. + /// + /// @param[in] s + /// Stream to which the output is copied. + //------------------------------------------------------------------ + virtual void + GetDescription(Stream *s); +}; + +//---------------------------------------------------------------------- +/// @class SearchFilter SearchFilter.h "lldb/Core/SearchFilter.h" +/// @brief Class descends through the SymbolContext space of the target, +/// applying a filter at each stage till it reaches the depth specified by +/// the GetDepth method of the searcher, and calls its callback at that point. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +/// General Outline: +/// Provides the callback and search depth for the SearchFilter search. +/// +/// The search is done by cooperation between the search filter and the searcher. +/// The search filter does the heavy work of recursing through the SymbolContext +/// space of the target program's symbol space. The Searcher specifies the depth +/// at which it wants its callback to be invoked. Note that since the resolution +/// of the Searcher may be greater than that of the SearchFilter, before the +/// Searcher qualifies an address it should pass it to "AddressPasses." +/// The default implementation is "Everything Passes." +//---------------------------------------------------------------------- + +class SearchFilter +{ +public: + + //------------------------------------------------------------------ + /// The basic constructor takes a Target, which gives the space to search. + /// + /// @param[in] target + /// The Target that provides the module list to search. + //------------------------------------------------------------------ + SearchFilter (const lldb::TargetSP &target_sp); + + SearchFilter (const SearchFilter& rhs); + + virtual + ~SearchFilter (); + + const SearchFilter& + operator=(const SearchFilter& rhs); + + //------------------------------------------------------------------ + /// Call this method with a file spec to see if that spec passes the filter. + /// + /// @param[in] spec + /// The file spec to check against the filter. + /// @return + /// \b true if \a spec passes, and \b false otherwise. + //------------------------------------------------------------------ + virtual bool + ModulePasses (const FileSpec &spec); + + //------------------------------------------------------------------ + /// Call this method with a Module to see if that module passes the filter. + /// + /// @param[in] module + /// The Module to check against the filter. + /// + /// @return + /// \b true if \a module passes, and \b false otherwise. + //------------------------------------------------------------------ + virtual bool + ModulePasses (const lldb::ModuleSP &module_sp); + + //------------------------------------------------------------------ + /// Call this method with a Address to see if \a address passes the filter. + /// + /// @param[in] addr + /// The address to check against the filter. + /// + /// @return + /// \b true if \a address passes, and \b false otherwise. + //------------------------------------------------------------------ + virtual bool + AddressPasses (Address &addr); + + //------------------------------------------------------------------ + /// Call this method with a FileSpec to see if \a file spec passes the filter + /// as the name of a compilation unit. + /// + /// @param[in] fileSpec + /// The file spec to check against the filter. + /// + /// @return + /// \b true if \a file spec passes, and \b false otherwise. + //------------------------------------------------------------------ + virtual bool + CompUnitPasses (FileSpec &fileSpec); + + //------------------------------------------------------------------ + /// Call this method with a CompileUnit to see if \a comp unit passes the filter. + /// + /// @param[in] compUnit + /// The CompileUnit to check against the filter. + /// + /// @return + /// \b true if \a Comp Unit passes, and \b false otherwise. + //------------------------------------------------------------------ + virtual bool + CompUnitPasses (CompileUnit &compUnit); + + //------------------------------------------------------------------ + /// Call this method to do the search using the Searcher. + /// + /// @param[in] searcher + /// The searcher to drive with this search. + /// + //------------------------------------------------------------------ + virtual void + Search (Searcher &searcher); + + //------------------------------------------------------------------ + /// Call this method to do the search using the Searcher in the module list + /// \a modules. + /// + /// @param[in] searcher + /// The searcher to drive with this search. + /// + /// @param[in] modules + /// The module list within which to restrict the search. + /// + //------------------------------------------------------------------ + virtual void + SearchInModuleList (Searcher &searcher, ModuleList &modules); + + //------------------------------------------------------------------ + /// This determines which items are REQUIRED for the filter to pass. + /// For instance, if you are filtering by Compilation Unit, obviously + /// symbols that have no compilation unit can't pass So return eSymbolContextCU + /// and search callbacks can then short cut the search to avoid looking at + /// things that obviously won't pass. + /// + /// @return + /// The required elements for the search, which is an or'ed together + /// set of lldb:SearchContextItem enum's. + /// + //------------------------------------------------------------------ + virtual uint32_t + GetFilterRequiredItems (); + + //------------------------------------------------------------------ + /// Prints a canonical description for the search filter to the stream \a s. + /// + /// @param[in] s + /// Stream to which the output is copied. + //------------------------------------------------------------------ + virtual void + GetDescription(Stream *s); + + //------------------------------------------------------------------ + /// Standard "Dump" method. At present it does nothing. + //------------------------------------------------------------------ + virtual void + Dump (Stream *s) const; + +protected: + + // These are utility functions to assist with the search iteration. They are used by the + // default Search method. + + Searcher::CallbackReturn + DoModuleIteration (const SymbolContext &context, + Searcher &searcher); + + Searcher::CallbackReturn + DoModuleIteration (const lldb::ModuleSP& module_sp, + Searcher &searcher); + + Searcher::CallbackReturn + DoCUIteration (const lldb::ModuleSP& module_sp, + const SymbolContext &context, + Searcher &searcher); + + Searcher::CallbackReturn + DoFunctionIteration (Function *function, + const SymbolContext &context, + Searcher &searcher); + + lldb::TargetSP m_target_sp; // Every filter has to be associated with a target for + // now since you need a starting place for the search. +}; + +//---------------------------------------------------------------------- +/// @class SearchFilterForNonModuleSpecificSearches SearchFilter.h "lldb/Core/SearchFilter.h" +/// @brief This is a SearchFilter that searches through all modules. It also consults the Target::ModuleIsExcludedForNonModuleSpecificSearches. +//---------------------------------------------------------------------- +class SearchFilterForNonModuleSpecificSearches : + public SearchFilter +{ +public: + SearchFilterForNonModuleSpecificSearches (const lldb::TargetSP &targetSP) : SearchFilter(targetSP) {} + ~SearchFilterForNonModuleSpecificSearches () {} + + virtual bool + ModulePasses (const FileSpec &module_spec); + + virtual bool + ModulePasses (const lldb::ModuleSP &module_sp); +}; + +//---------------------------------------------------------------------- +/// @class SearchFilterByModule SearchFilter.h "lldb/Core/SearchFilter.h" +/// @brief This is a SearchFilter that restricts the search to a given module. +//---------------------------------------------------------------------- + +class SearchFilterByModule : + public SearchFilter +{ +public: + + //------------------------------------------------------------------ + /// The basic constructor takes a Target, which gives the space to search, + /// and the module to restrict the search to. + /// + /// @param[in] target + /// The Target that provides the module list to search. + /// + /// @param[in] module + /// The Module that limits the search. + //------------------------------------------------------------------ + SearchFilterByModule (const lldb::TargetSP &targetSP, + const FileSpec &module); + + SearchFilterByModule (const SearchFilterByModule& rhs); + + virtual + ~SearchFilterByModule (); + + const SearchFilterByModule& + operator=(const SearchFilterByModule& rhs); + + virtual bool + ModulePasses (const lldb::ModuleSP &module_sp); + + virtual bool + ModulePasses (const FileSpec &spec); + + virtual bool + AddressPasses (Address &address); + + virtual bool + CompUnitPasses (FileSpec &fileSpec); + + virtual bool + CompUnitPasses (CompileUnit &compUnit); + + virtual void + GetDescription(Stream *s); + + virtual uint32_t + GetFilterRequiredItems (); + + virtual void + Dump (Stream *s) const; + + virtual void + Search (Searcher &searcher); + +private: + FileSpec m_module_spec; +}; + +class SearchFilterByModuleList : + public SearchFilter +{ +public: + + //------------------------------------------------------------------ + /// The basic constructor takes a Target, which gives the space to search, + /// and the module list to restrict the search to. + /// + /// @param[in] target + /// The Target that provides the module list to search. + /// + /// @param[in] module + /// The Module that limits the search. + //------------------------------------------------------------------ + SearchFilterByModuleList (const lldb::TargetSP &targetSP, + const FileSpecList &module_list); + + SearchFilterByModuleList (const SearchFilterByModuleList& rhs); + + virtual + ~SearchFilterByModuleList (); + + const SearchFilterByModuleList& + operator=(const SearchFilterByModuleList& rhs); + + virtual bool + ModulePasses (const lldb::ModuleSP &module_sp); + + virtual bool + ModulePasses (const FileSpec &spec); + + virtual bool + AddressPasses (Address &address); + + virtual bool + CompUnitPasses (FileSpec &fileSpec); + + virtual bool + CompUnitPasses (CompileUnit &compUnit); + + virtual void + GetDescription(Stream *s); + + virtual uint32_t + GetFilterRequiredItems (); + + virtual void + Dump (Stream *s) const; + + virtual void + Search (Searcher &searcher); + +private: + FileSpecList m_module_spec_list; +}; + +class SearchFilterByModuleListAndCU : + public SearchFilterByModuleList +{ +public: + + //------------------------------------------------------------------ + /// The basic constructor takes a Target, which gives the space to search, + /// and the module list to restrict the search to. + /// + /// @param[in] target + /// The Target that provides the module list to search. + /// + /// @param[in] module + /// The Module that limits the search. + //------------------------------------------------------------------ + SearchFilterByModuleListAndCU (const lldb::TargetSP &targetSP, + const FileSpecList &module_list, + const FileSpecList &cu_list); + + SearchFilterByModuleListAndCU (const SearchFilterByModuleListAndCU& rhs); + + virtual + ~SearchFilterByModuleListAndCU (); + + const SearchFilterByModuleListAndCU& + operator=(const SearchFilterByModuleListAndCU& rhs); + + virtual bool + AddressPasses (Address &address); + + virtual bool + CompUnitPasses (FileSpec &fileSpec); + + virtual bool + CompUnitPasses (CompileUnit &compUnit); + + virtual void + GetDescription(Stream *s); + + virtual uint32_t + GetFilterRequiredItems (); + + virtual void + Dump (Stream *s) const; + + virtual void + Search (Searcher &searcher); + +private: + FileSpecList m_module_spec_list; + FileSpecList m_cu_spec_list; +}; + +} // namespace lldb_private + +#endif // liblldb_SearchFilter_h_ diff --git a/include/lldb/Core/Section.h b/include/lldb/Core/Section.h new file mode 100644 index 0000000..437eaf5 --- /dev/null +++ b/include/lldb/Core/Section.h @@ -0,0 +1,313 @@ +//===-- Section.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_Section_h_ +#define liblldb_Section_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/Flags.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/UserID.h" +#include "lldb/Core/VMRange.h" +#include "lldb/Symbol/ObjectFile.h" +#include <limits.h> + +namespace lldb_private { + +class SectionList +{ +public: + typedef std::vector<lldb::SectionSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + SectionList(); + + ~SectionList(); + + SectionList & + operator =(const SectionList& rhs); + + size_t + AddSection (const lldb::SectionSP& section_sp); + + size_t + AddUniqueSection (const lldb::SectionSP& section_sp); + + size_t + FindSectionIndex (const Section* sect); + + bool + ContainsSection(lldb::user_id_t sect_id) const; + + void + Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const; + + lldb::SectionSP + FindSectionByName (const ConstString §ion_dstr) const; + + lldb::SectionSP + FindSectionByID (lldb::user_id_t sect_id) const; + + lldb::SectionSP + FindSectionByType (lldb::SectionType sect_type, bool check_children, size_t start_idx = 0) const; + + lldb::SectionSP + FindSectionContainingFileAddress (lldb::addr_t addr, uint32_t depth = UINT32_MAX) const; + + bool + GetSectionData (const DataExtractor& module_data, DataExtractor& section_data) const; + + // Get the number of sections in this list only + size_t + GetSize () const + { + return m_sections.size(); + } + + // Get the number of sections in this list, and any contained child sections + size_t + GetNumSections (uint32_t depth) const; + + bool + ReplaceSection (lldb::user_id_t sect_id, const lldb::SectionSP& section_sp, uint32_t depth = UINT32_MAX); + + // Warning, this can be slow as it's removing items from a std::vector. + bool + DeleteSection (size_t idx); + + lldb::SectionSP + GetSectionAtIndex (size_t idx) const; + + size_t + Slide (lldb::addr_t slide_amount, bool slide_children); + + void + Clear () + { + m_sections.clear(); + } + +protected: + collection m_sections; +}; + + +class Section : + public std::enable_shared_from_this<Section>, + public ModuleChild, + public UserID, + public Flags +{ +public: + // Create a root section (one that has no parent) + Section (const lldb::ModuleSP &module_sp, + ObjectFile *obj_file, + lldb::user_id_t sect_id, + const ConstString &name, + lldb::SectionType sect_type, + lldb::addr_t file_vm_addr, + lldb::addr_t vm_size, + lldb::offset_t file_offset, + lldb::offset_t file_size, + uint32_t flags); + + // Create a section that is a child of parent_section_sp + Section (const lldb::SectionSP &parent_section_sp, // NULL for top level sections, non-NULL for child sections + const lldb::ModuleSP &module_sp, + ObjectFile *obj_file, + lldb::user_id_t sect_id, + const ConstString &name, + lldb::SectionType sect_type, + lldb::addr_t file_vm_addr, + lldb::addr_t vm_size, + lldb::offset_t file_offset, + lldb::offset_t file_size, + uint32_t flags); + + ~Section (); + + static int + Compare (const Section& a, const Section& b); + + bool + ContainsFileAddress (lldb::addr_t vm_addr) const; + + SectionList& + GetChildren () + { + return m_children; + } + + const SectionList& + GetChildren () const + { + return m_children; + } + + void + Dump (Stream *s, Target *target, uint32_t depth) const; + + void + DumpName (Stream *s) const; + + lldb::addr_t + GetLoadBaseAddress (Target *target) const; + + bool + ResolveContainedAddress (lldb::addr_t offset, Address &so_addr) const; + + lldb::offset_t + GetFileOffset () const + { + return m_file_offset; + } + + void + SetFileOffset (lldb::offset_t file_offset) + { + m_file_offset = file_offset; + } + + lldb::offset_t + GetFileSize () const + { + return m_file_size; + } + + void + SetFileSize (lldb::offset_t file_size) + { + m_file_size = file_size; + } + + lldb::addr_t + GetFileAddress () const; + + bool + SetFileAddress (lldb::addr_t file_addr); + + lldb::addr_t + GetOffset () const; + + + lldb::addr_t + GetByteSize () const + { + return m_byte_size; + } + + void + SetByteSize (lldb::addr_t byte_size) + { + m_byte_size = byte_size; + } + + bool + IsFake() const + { + return m_fake; + } + + void + SetIsFake(bool fake) + { + m_fake = fake; + } + + bool + IsEncrypted () const + { + return m_encrypted; + } + + void + SetIsEncrypted (bool b) + { + m_encrypted = b; + } + + bool + IsDescendant (const Section *section); + + const ConstString& + GetName () const + { + return m_name; + } + + bool + Slide (lldb::addr_t slide_amount, bool slide_children); + + + lldb::SectionType + GetType () const + { + return m_type; + } + + lldb::SectionSP + GetParent () const + { + return m_parent_wp.lock(); + } + + bool + IsThreadSpecific () const + { + return m_thread_specific; + } + + void + SetIsThreadSpecific (bool b) + { + m_thread_specific = b; + } + + ObjectFile * + GetObjectFile () + { + return m_obj_file; + } + const ObjectFile * + GetObjectFile () const + { + return m_obj_file; + } + + +protected: + + ObjectFile *m_obj_file; // The object file that data for this section should be read from + lldb::SectionType m_type; // The type of this section + lldb::SectionWP m_parent_wp; // Weak pointer to parent section + ConstString m_name; // Name of this section + lldb::addr_t m_file_addr; // The absolute file virtual address range of this section if m_parent == NULL, + // offset from parent file virtual address if m_parent != NULL + lldb::addr_t m_byte_size; // Size in bytes that this section will occupy in memory at runtime + lldb::offset_t m_file_offset; // Object file offset (if any) + lldb::offset_t m_file_size; // Object file size (can be smaller than m_byte_size for zero filled sections...) + SectionList m_children; // Child sections + bool m_fake:1, // If true, then this section only can contain the address if one of its + // children contains an address. This allows for gaps between the children + // that are contained in the address range for this section, but do not produce + // hits unless the children contain the address. + m_encrypted:1, // Set to true if the contents are encrypted + m_thread_specific:1;// This section is thread specific +private: + DISALLOW_COPY_AND_ASSIGN (Section); +}; + + +} // namespace lldb_private + +#endif // liblldb_Section_h_ diff --git a/include/lldb/Core/SourceManager.h b/include/lldb/Core/SourceManager.h new file mode 100644 index 0000000..b850df7 --- /dev/null +++ b/include/lldb/Core/SourceManager.h @@ -0,0 +1,196 @@ +//===-- SourceManager.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_SourceManager_h_ +#define liblldb_SourceManager_h_ + +// C Includes +// C++ Includes +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Host/FileSpec.h" + +namespace lldb_private { + +class SourceManager +{ +public: +#ifndef SWIG + + class File + { + friend bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs); + public: + + File (const FileSpec &file_spec, Target *target); + ~File(); + + size_t + DisplaySourceLines (uint32_t line, + uint32_t context_before, + uint32_t context_after, + Stream *s); + void + FindLinesMatchingRegex (RegularExpression& regex, + uint32_t start_line, + uint32_t end_line, + std::vector<uint32_t> &match_lines); + + bool + GetLine (uint32_t line_no, std::string &buffer); + + uint32_t + GetLineOffset (uint32_t line); + + bool + LineIsValid (uint32_t line); + + bool + FileSpecMatches (const FileSpec &file_spec); + + const FileSpec & + GetFileSpec () + { + return m_file_spec; + } + + uint32_t + GetSourceMapModificationID() const + { + return m_source_map_mod_id; + } + + protected: + + bool + CalculateLineOffsets (uint32_t line = UINT32_MAX); + + FileSpec m_file_spec_orig; // The original file spec that was used (can be different from m_file_spec) + FileSpec m_file_spec; // The actualy file spec being used (if the target has source mappings, this might be different from m_file_spec_orig) + TimeValue m_mod_time; // Keep the modification time that this file data is valid for + uint32_t m_source_map_mod_id; // If the target uses path remappings, be sure to clear our notion of a source file if the path modification ID changes + lldb::DataBufferSP m_data_sp; + typedef std::vector<uint32_t> LineOffsets; + LineOffsets m_offsets; + }; + +#endif // SWIG + + typedef std::shared_ptr<File> FileSP; + +#ifndef SWIG + + // The SourceFileCache class separates the source manager from the cache of source files, so the + // cache can be stored in the Debugger, but the source managers can be per target. + class SourceFileCache + { + public: + SourceFileCache () {} + ~SourceFileCache() {} + + void AddSourceFile (const FileSP &file_sp); + FileSP FindSourceFile (const FileSpec &file_spec) const; + + protected: + typedef std::map <FileSpec, FileSP> FileCache; + FileCache m_file_cache; + }; +#endif + + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + // A source manager can be made with a non-null target, in which case it can use the path remappings to find + // source files that are not in their build locations. With no target it won't be able to do this. + SourceManager (const lldb::DebuggerSP &debugger_sp); + SourceManager (const lldb::TargetSP &target_sp); + + ~SourceManager(); + + + FileSP + GetLastFile () + { + return m_last_file_sp; + } + + size_t + DisplaySourceLinesWithLineNumbers (const FileSpec &file, + uint32_t line, + uint32_t context_before, + uint32_t context_after, + const char* current_line_cstr, + Stream *s, + const SymbolContextList *bp_locs = NULL); + + // This variant uses the last file we visited. + size_t + DisplaySourceLinesWithLineNumbersUsingLastFile (uint32_t start_line, + uint32_t count, + uint32_t curr_line, + const char* current_line_cstr, + Stream *s, + const SymbolContextList *bp_locs = NULL); + + size_t + DisplayMoreWithLineNumbers (Stream *s, + uint32_t count, + bool reverse, + const SymbolContextList *bp_locs = NULL); + + bool + SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line); + + bool + GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line); + + bool + DefaultFileAndLineSet () + { + return (m_last_file_sp.get() != NULL); + } + + void + FindLinesMatchingRegex (FileSpec &file_spec, + RegularExpression& regex, + uint32_t start_line, + uint32_t end_line, + std::vector<uint32_t> &match_lines); + +protected: + + FileSP + GetFile (const FileSpec &file_spec); + + //------------------------------------------------------------------ + // Classes that inherit from SourceManager can see and modify these + //------------------------------------------------------------------ + FileSP m_last_file_sp; + uint32_t m_last_line; + uint32_t m_last_count; + bool m_default_set; + lldb::TargetWP m_target_wp; + lldb::DebuggerWP m_debugger_wp; + +private: + //------------------------------------------------------------------ + // For SourceManager only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (SourceManager); +}; + +bool operator== (const SourceManager::File &lhs, const SourceManager::File &rhs); +} // namespace lldb_private + +#endif // liblldb_SourceManager_h_ diff --git a/include/lldb/Core/State.h b/include/lldb/Core/State.h new file mode 100644 index 0000000..8057b3e --- /dev/null +++ b/include/lldb/Core/State.h @@ -0,0 +1,78 @@ +//===-- State.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_State_h_ +#define liblldb_State_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//------------------------------------------------------------------ +/// Converts a StateType to a C string. +/// +/// @param[in] state +/// The StateType object to convert. +/// +/// @return +/// A NULL terminated C string that describes \a state. The +/// returned string comes from constant string buffers and does +/// not need to be freed. +//------------------------------------------------------------------ +const char * +StateAsCString (lldb::StateType state); + +//------------------------------------------------------------------ +/// Check if a state represents a state where the process or thread +/// is running. +/// +/// @param[in] state +/// The StateType enumeration value +/// +/// @return +/// \b true if the state represents a process or thread state +/// where the process or thread is running, \b false otherwise. +//------------------------------------------------------------------ +bool +StateIsRunningState (lldb::StateType state); + +//------------------------------------------------------------------ +/// Check if a state represents a state where the process or thread +/// is stopped. Stopped can mean stopped when the process is still +/// around, or stopped when the process has exited or doesn't exist +/// yet. The \a must_exist argument tells us which of these cases is +/// desired. +/// +/// @param[in] state +/// The StateType enumeration value +/// +/// @param[in] must_exist +/// A boolean that indicates the thread must also be alive +/// so states like unloaded or exited won't return true. +/// +/// @return +/// \b true if the state represents a process or thread state +/// where the process or thread is stopped. If \a must_exist is +/// \b true, then the process can't be exited or unloaded, +/// otherwise exited and unloaded or other states where the +/// process no longer exists are considered to be stopped. +//------------------------------------------------------------------ +bool +StateIsStoppedState (lldb::StateType state, bool must_exist); + +const char * +GetPermissionsAsCString (uint32_t permissions); + +} // namespace lldb_private + +#endif // liblldb_State_h_ diff --git a/include/lldb/Core/Stream.h b/include/lldb/Core/Stream.h new file mode 100644 index 0000000..0fd4aac --- /dev/null +++ b/include/lldb/Core/Stream.h @@ -0,0 +1,612 @@ +//===-- Stream.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_Stream_h_ +#define liblldb_Stream_h_ +#if defined(__cplusplus) + +#include "lldb/lldb-private.h" +#include "lldb/Core/Flags.h" +#include <stdarg.h> + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Stream Stream.h "lldb/Core/Stream.h" +/// @brief A stream class that can stream formatted output to a file. +//---------------------------------------------------------------------- +class Stream +{ +public: + //------------------------------------------------------------------ + /// \a m_flags bit values. + //------------------------------------------------------------------ + enum + { + eVerbose = (1 << 0), ///< If set, verbose logging is enabled + eDebug = (1 << 1), ///< If set, debug logging is enabled + eAddPrefix = (1 << 2), ///< Add number prefixes for binary, octal and hex when eBinary is clear + eBinary = (1 << 3) ///< Get and put data as binary instead of as the default string mode. + }; + + //------------------------------------------------------------------ + /// Construct with flags and address size and byte order. + /// + /// Construct with dump flags \a flags and the default address + /// size. \a flags can be any of the above enumeration logical OR'ed + /// together. + //------------------------------------------------------------------ + Stream (uint32_t flags, + uint32_t addr_size, + lldb::ByteOrder byte_order); + + //------------------------------------------------------------------ + /// Construct a default Stream, not binary, host byte order and + /// host addr size. + /// + //------------------------------------------------------------------ + Stream (); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual + ~Stream (); + + //------------------------------------------------------------------ + // Subclasses must override these methods + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Flush the stream. + /// + /// Subclasses should flush the stream to make any output appear + /// if the stream has any buffering. + //------------------------------------------------------------------ + virtual void + Flush () = 0; + + //------------------------------------------------------------------ + /// Output character bytes to the stream. + /// + /// Appends \a src_len characters from the buffer \a src to the + /// stream. + /// + /// @param[in] src + /// A buffer containing at least \a src_len bytes of data. + /// + /// @param[in] src_len + /// A number of bytes to append to the stream. + /// + /// @return + /// The number of bytes that were appended to the stream. + //------------------------------------------------------------------ + virtual size_t + Write (const void *src, size_t src_len) = 0; + + //------------------------------------------------------------------ + // Member functions + //------------------------------------------------------------------ + size_t + PutChar (char ch); + + //------------------------------------------------------------------ + /// Set the byte_order value. + /// + /// Sets the byte order of the data to extract. Extracted values + /// will be swapped if necessary when decoding. + /// + /// @param[in] byte_order + /// The byte order value to use when extracting data. + /// + /// @return + /// The old byte order value. + //------------------------------------------------------------------ + lldb::ByteOrder + SetByteOrder (lldb::ByteOrder byte_order); + + //------------------------------------------------------------------ + /// Format a C string from a printf style format and variable + /// arguments and encode and append the resulting C string as hex + /// bytes. + /// + /// @param[in] format + /// A printf style format string. + /// + /// @param[in] ... + /// Any additional arguments needed for the printf format string. + /// + /// @return + /// The number of bytes that were appended to the stream. + //------------------------------------------------------------------ + size_t + PrintfAsRawHex8 (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + //------------------------------------------------------------------ + /// Format a C string from a printf style format and variable + /// arguments and encode and append the resulting C string as hex + /// bytes. + /// + /// @param[in] format + /// A printf style format string. + /// + /// @param[in] ... + /// Any additional arguments needed for the printf format string. + /// + /// @return + /// The number of bytes that were appended to the stream. + //------------------------------------------------------------------ + size_t + PutHex8 (uint8_t uvalue); + + size_t + PutNHex8 (size_t n, uint8_t uvalue); + + size_t + PutHex16 (uint16_t uvalue, + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); + + size_t + PutHex32 (uint32_t uvalue, + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); + + size_t + PutHex64 (uint64_t uvalue, + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); + + size_t + PutMaxHex64 (uint64_t uvalue, + size_t byte_size, + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); + size_t + PutFloat (float f, + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); + + size_t + PutDouble (double d, + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); + + size_t + PutLongDouble (long double ld, + lldb::ByteOrder byte_order = lldb::eByteOrderInvalid); + + size_t + PutPointer (void *ptr); + + // Append \a src_len bytes from \a src to the stream as hex characters + // (two ascii characters per byte of input data) + size_t + PutBytesAsRawHex8 (const void *src, + size_t src_len, + lldb::ByteOrder src_byte_order = lldb::eByteOrderInvalid, + lldb::ByteOrder dst_byte_order = lldb::eByteOrderInvalid); + + // Append \a src_len bytes from \a s to the stream as binary data. + size_t + PutRawBytes (const void *s, + size_t src_len, + lldb::ByteOrder src_byte_order = lldb::eByteOrderInvalid, + lldb::ByteOrder dst_byte_order = lldb::eByteOrderInvalid); + + size_t + PutCStringAsRawHex8 (const char *s); + + //------------------------------------------------------------------ + /// Output a NULL terminated C string \a cstr to the stream \a s. + /// + /// @param[in] cstr + /// A NULL terminated C string. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (const char *cstr); + + //------------------------------------------------------------------ + /// Output a pointer value \a p to the stream \a s. + /// + /// @param[in] p + /// A void pointer. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (void *p); + + //------------------------------------------------------------------ + /// Output a character \a ch to the stream \a s. + /// + /// @param[in] ch + /// A printable character value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (char ch); + + //------------------------------------------------------------------ + /// Output a uint8_t \a uval to the stream \a s. + /// + /// @param[in] uval + /// A uint8_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (uint8_t uval); + + //------------------------------------------------------------------ + /// Output a uint16_t \a uval to the stream \a s. + /// + /// @param[in] uval + /// A uint16_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (uint16_t uval); + + //------------------------------------------------------------------ + /// Output a uint32_t \a uval to the stream \a s. + /// + /// @param[in] uval + /// A uint32_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (uint32_t uval); + + //------------------------------------------------------------------ + /// Output a uint64_t \a uval to the stream \a s. + /// + /// @param[in] uval + /// A uint64_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (uint64_t uval); + + //------------------------------------------------------------------ + /// Output a int8_t \a sval to the stream \a s. + /// + /// @param[in] sval + /// A int8_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (int8_t sval); + + //------------------------------------------------------------------ + /// Output a int16_t \a sval to the stream \a s. + /// + /// @param[in] sval + /// A int16_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (int16_t sval); + + //------------------------------------------------------------------ + /// Output a int32_t \a sval to the stream \a s. + /// + /// @param[in] sval + /// A int32_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (int32_t sval); + + //------------------------------------------------------------------ + /// Output a int64_t \a sval to the stream \a s. + /// + /// @param[in] sval + /// A int64_t value. + /// + /// @return + /// A reference to this class so multiple things can be streamed + /// in one statement. + //------------------------------------------------------------------ + Stream& + operator<< (int64_t sval); + + //------------------------------------------------------------------ + /// Output an address value to this stream. + /// + /// Put an address \a addr out to the stream with optional \a prefix + /// and \a suffix strings. + /// + /// @param[in] addr + /// An address value. + /// + /// @param[in] addr_size + /// Size in bytes of the address, used for formatting. + /// + /// @param[in] prefix + /// A prefix C string. If NULL, no prefix will be output. + /// + /// @param[in] suffix + /// A suffix C string. If NULL, no suffix will be output. + //------------------------------------------------------------------ + void + Address (uint64_t addr, uint32_t addr_size, const char *prefix = NULL, const char *suffix = NULL); + + //------------------------------------------------------------------ + /// Output an address range to this stream. + /// + /// Put an address range \a lo_addr - \a hi_addr out to the stream + /// with optional \a prefix and \a suffix strings. + /// + /// @param[in] lo_addr + /// The start address of the address range. + /// + /// @param[in] hi_addr + /// The end address of the address range. + /// + /// @param[in] addr_size + /// Size in bytes of the address, used for formatting. + /// + /// @param[in] prefix + /// A prefix C string. If NULL, no prefix will be output. + /// + /// @param[in] suffix + /// A suffix C string. If NULL, no suffix will be output. + //------------------------------------------------------------------ + void + AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix = NULL, const char *suffix = NULL); + + //------------------------------------------------------------------ + /// Output a C string to the stream. + /// + /// Print a C string \a cstr to the stream. + /// + /// @param[in] cstr + /// The string to be output to the stream. + //------------------------------------------------------------------ + size_t + PutCString (const char *cstr); + + //------------------------------------------------------------------ + /// Output and End of Line character to the stream. + //------------------------------------------------------------------ + size_t + EOL(); + + //------------------------------------------------------------------ + /// Get the address size in bytes. + /// + /// @return + /// The size of an address in bytes that is used when outputting + /// address and pointer values to the stream. + //------------------------------------------------------------------ + uint32_t + GetAddressByteSize () const; + + //------------------------------------------------------------------ + /// Test if debug logging is enabled. + /// + /// @return + // \b true if the debug flag bit is set in this stream, \b + // false otherwise. + //------------------------------------------------------------------ + bool + GetDebug() const; + + //------------------------------------------------------------------ + /// The flags accessor. + /// + /// @return + /// A reference to the Flags member variable. + //------------------------------------------------------------------ + Flags& + GetFlags(); + + //------------------------------------------------------------------ + /// The flags const accessor. + /// + /// @return + /// A const reference to the Flags member variable. + //------------------------------------------------------------------ + const Flags& + GetFlags() const; + + //------------------------------------------------------------------ + //// The byte order accessor. + //// + //// @return + //// The byte order. + //------------------------------------------------------------------ + lldb::ByteOrder + GetByteOrder() const; + + //------------------------------------------------------------------ + /// Get the current indentation level. + /// + /// @return + /// The current indentation level as an integer. + //------------------------------------------------------------------ + int + GetIndentLevel () const; + + //------------------------------------------------------------------ + /// Test if verbose logging is enabled. + /// + /// @return + // \b true if the verbose flag bit is set in this stream, \b + // false otherwise. + //------------------------------------------------------------------ + bool + GetVerbose() const; + + //------------------------------------------------------------------ + /// Indent the current line in the stream. + /// + /// Indent the current line using the current indentation level and + /// print an optional string following the idenatation spaces. + /// + /// @param[in] s + /// A C string to print following the indentation. If NULL, just + /// output the indentation characters. + //------------------------------------------------------------------ + size_t + Indent(const char *s = NULL); + + //------------------------------------------------------------------ + /// Decrement the current indentation level. + //------------------------------------------------------------------ + void + IndentLess (int amount = 2); + + //------------------------------------------------------------------ + /// Increment the current indentation level. + //------------------------------------------------------------------ + void + IndentMore (int amount = 2); + + //------------------------------------------------------------------ + /// Output an offset value. + /// + /// Put an offset \a uval out to the stream using the printf format + /// in \a format. + /// + /// @param[in] offset + /// The offset value. + /// + /// @param[in] format + /// The printf style format to use when outputting the offset. + //------------------------------------------------------------------ + void + Offset (uint32_t offset, const char *format = "0x%8.8x: "); + + //------------------------------------------------------------------ + /// Output printf formatted output to the stream. + /// + /// Print some formatted output to the stream. + /// + /// @param[in] format + /// A printf style format string. + /// + /// @param[in] ... + /// Variable arguments that are needed for the printf style + /// format string \a format. + //------------------------------------------------------------------ + size_t + Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + size_t + PrintfVarArg(const char *format, va_list args); + + //------------------------------------------------------------------ + /// Output a quoted C string value to the stream. + /// + /// Print a double quoted NULL terminated C string to the stream + /// using the printf format in \a format. + /// + /// @param[in] cstr + /// A NULL terminated C string value. + /// + /// @param[in] format + /// The optional C string format that can be overridden. + //------------------------------------------------------------------ + void + QuotedCString (const char *cstr, const char *format = "\"%s\""); + + //------------------------------------------------------------------ + /// Set the address size in bytes. + /// + /// @param[in] addr_size + /// The new size in bytes of an address to use when outputting + /// address and pointer values. + //------------------------------------------------------------------ + void + SetAddressByteSize (uint32_t addr_size); + + //------------------------------------------------------------------ + /// Set the current indentation level. + /// + /// @param[in] level + /// The new indentation level. + //------------------------------------------------------------------ + void + SetIndentLevel (int level); + + //------------------------------------------------------------------ + /// Output a SLEB128 number to the stream. + /// + /// Put an SLEB128 \a uval out to the stream using the printf format + /// in \a format. + /// + /// @param[in] uval + /// A uint64_t value that was extracted as a SLEB128 value. + /// + /// @param[in] format + /// The optional printf format that can be overridden. + //------------------------------------------------------------------ + size_t + PutSLEB128 (int64_t uval); + + //------------------------------------------------------------------ + /// Output a ULEB128 number to the stream. + /// + /// Put an ULEB128 \a uval out to the stream using the printf format + /// in \a format. + /// + /// @param[in] uval + /// A uint64_t value that was extracted as a ULEB128 value. + /// + /// @param[in] format + /// The optional printf format that can be overridden. + //------------------------------------------------------------------ + size_t + PutULEB128 (uint64_t uval); + + static void + UnitTest(Stream *s); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + Flags m_flags; ///< Dump flags. + uint32_t m_addr_size; ///< Size of an address in bytes. + lldb::ByteOrder m_byte_order; ///< Byte order to use when encoding scalar types. + int m_indent_level; ///< Indention level. + + size_t _PutHex8 (uint8_t uvalue, bool add_prefix); +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Stream_h_ + diff --git a/include/lldb/Core/StreamAsynchronousIO.h b/include/lldb/Core/StreamAsynchronousIO.h new file mode 100644 index 0000000..0e3e9ee --- /dev/null +++ b/include/lldb/Core/StreamAsynchronousIO.h @@ -0,0 +1,42 @@ +//===-- StreamAsynchronousIO.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_StreamAsynchronousIO_h_ +#define liblldb_StreamAsynchronousIO_h_ + +#include <string> + +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" + +namespace lldb_private { + +class StreamAsynchronousIO : + public Stream +{ +public: + StreamAsynchronousIO (Broadcaster &broadcaster, uint32_t broadcast_event_type); + + virtual ~StreamAsynchronousIO (); + + virtual void + Flush (); + + virtual size_t + Write (const void *src, size_t src_len); + + +private: + Broadcaster &m_broadcaster; + uint32_t m_broadcast_event_type; + StreamString m_accumulated_data; +}; + +} // namespace lldb_private +#endif // #ifndef liblldb_StreamAsynchronousIO_h diff --git a/include/lldb/Core/StreamBuffer.h b/include/lldb/Core/StreamBuffer.h new file mode 100644 index 0000000..9d25e84 --- /dev/null +++ b/include/lldb/Core/StreamBuffer.h @@ -0,0 +1,87 @@ +//===-- StreamBuffer.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_StreamBuffer_h_ +#define liblldb_StreamBuffer_h_ + +#include <stdio.h> +#include <string> +#include "llvm/ADT/SmallVector.h" +#include "lldb/Core/Stream.h" + +namespace lldb_private { + +template <unsigned N> +class StreamBuffer : public Stream +{ +public: + StreamBuffer () : + Stream (0, 4, lldb::eByteOrderBig), + m_packet () + { + } + + + StreamBuffer (uint32_t flags, + uint32_t addr_size, + lldb::ByteOrder byte_order) : + Stream (flags, addr_size, byte_order), + m_packet () + { + } + + virtual + ~StreamBuffer () + { + } + + virtual void + Flush () + { + // Nothing to do when flushing a buffer based stream... + } + + virtual size_t + Write (const void *s, size_t length) + { + if (s && length) + m_packet.append ((const char *)s, ((const char *)s) + length); + return length; + } + + void + Clear() + { + m_packet.clear(); + } + + // Beware, this might not be NULL terminated as you can expect from + // StringString as there may be random bits in the llvm::SmallVector. If + // you are using this class to create a C string, be sure the call PutChar ('\0') + // after you have created your string, or use StreamString. + const char * + GetData () const + { + return m_packet.data(); + } + + size_t + GetSize() const + { + return m_packet.size(); + } + +protected: + llvm::SmallVector<char, N> m_packet; + +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_StreamBuffer_h_ diff --git a/include/lldb/Core/StreamCallback.h b/include/lldb/Core/StreamCallback.h new file mode 100644 index 0000000..b5fb91c --- /dev/null +++ b/include/lldb/Core/StreamCallback.h @@ -0,0 +1,47 @@ +//===-- StreamCallback.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_StreamCallback_h_ +#define liblldb_StreamCallback_h_ + +#include <string> + +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class StreamCallback : + public Stream +{ +public: + StreamCallback (lldb::LogOutputCallback callback, void *baton); + + virtual ~StreamCallback (); + + virtual void + Flush (); + + virtual size_t + Write (const void *src, size_t src_len); + + +private: + typedef std::map<lldb::tid_t, StreamString> collection; + lldb::LogOutputCallback m_callback; + void *m_baton; + collection m_accumulated_data; + Mutex m_collection_mutex; + + StreamString &FindStreamForThread(lldb::tid_t cur_tid); +}; + +} // namespace lldb_private +#endif // #ifndef liblldb_StreamCallback_h diff --git a/include/lldb/Core/StreamFile.h b/include/lldb/Core/StreamFile.h new file mode 100644 index 0000000..d032c0b --- /dev/null +++ b/include/lldb/Core/StreamFile.h @@ -0,0 +1,75 @@ +//===-- StreamFile.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_StreamFile_h_ +#define liblldb_StreamFile_h_ + +// C Includes +// C++ Includes + +#include <string> + +// Other libraries and framework includes +// Project includes + +#include "lldb/Core/Stream.h" +#include "lldb/Host/File.h" + +namespace lldb_private { + +class StreamFile : public Stream +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StreamFile (); + + StreamFile (uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order); + + StreamFile (int fd, bool transfer_ownership); + + StreamFile (const char *path); + + StreamFile (FILE *fh, bool transfer_ownership); + + virtual + ~StreamFile(); + + File & + GetFile () + { + return m_file; + } + + const File & + GetFile () const + { + return m_file; + } + + virtual void + Flush (); + + virtual size_t + Write (const void *s, size_t length); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from StreamFile can see and modify these + //------------------------------------------------------------------ + File m_file; + +private: + DISALLOW_COPY_AND_ASSIGN (StreamFile); +}; + +} // namespace lldb_private + +#endif // liblldb_StreamFile_h_ diff --git a/include/lldb/Core/StreamString.h b/include/lldb/Core/StreamString.h new file mode 100644 index 0000000..a26ad2d --- /dev/null +++ b/include/lldb/Core/StreamString.h @@ -0,0 +1,64 @@ +//===-- StreamString.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_StreamString_h_ +#define liblldb_StreamString_h_ + +#include <string> + +#include "lldb/Core/Stream.h" + +namespace lldb_private { + +class StreamString : public Stream +{ +public: + StreamString (); + + StreamString (uint32_t flags, + uint32_t addr_size, + lldb::ByteOrder byte_order); + + virtual + ~StreamString (); + + virtual void + Flush (); + + virtual size_t + Write (const void *s, size_t length); + + void + Clear(); + + bool + Empty() const; + + const char * + GetData () const; + + size_t + GetSize() const; + + std::string & + GetString(); + + const std::string & + GetString() const; + + void + FillLastLineToColumn (uint32_t column, char fill_char); + +protected: + std::string m_packet; + +}; + +} // namespace lldb_private +#endif // #ifndef liblldb_StreamString_h_ diff --git a/include/lldb/Core/StreamTee.h b/include/lldb/Core/StreamTee.h new file mode 100644 index 0000000..e2a29a3 --- /dev/null +++ b/include/lldb/Core/StreamTee.h @@ -0,0 +1,175 @@ +//===-- StreamTee.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_StreamTee_h_ +#define liblldb_StreamTee_h_ + +#include <limits.h> + +#include "lldb/Core/Stream.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class StreamTee : public Stream +{ +public: + StreamTee () : + Stream (), + m_streams_mutex (Mutex::eMutexTypeRecursive), + m_streams () + { + } + + StreamTee (lldb::StreamSP &stream_sp): + Stream (), + m_streams_mutex (Mutex::eMutexTypeRecursive), + m_streams () + { + // No need to lock mutex during construction + if (stream_sp) + m_streams.push_back (stream_sp); + } + + + StreamTee (lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) : + Stream (), + m_streams_mutex (Mutex::eMutexTypeRecursive), + m_streams () + { + // No need to lock mutex during construction + if (stream_sp) + m_streams.push_back (stream_sp); + if (stream_2_sp) + m_streams.push_back (stream_2_sp); + } + + StreamTee (const StreamTee &rhs) : + Stream (rhs), + m_streams_mutex (Mutex::eMutexTypeRecursive), + m_streams() // Don't copy until we lock down "rhs" + { + Mutex::Locker locker (rhs.m_streams_mutex); + m_streams = rhs.m_streams; + } + + virtual + ~StreamTee () + { + } + + StreamTee & + operator = (const StreamTee &rhs) + { + if (this != &rhs) { + Stream::operator=(rhs); + Mutex::Locker lhs_locker (m_streams_mutex); + Mutex::Locker rhs_locker (rhs.m_streams_mutex); + m_streams = rhs.m_streams; + } + return *this; + } + + virtual void + Flush () + { + Mutex::Locker locker (m_streams_mutex); + collection::iterator pos, end; + for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) + { + // Allow for our collection to contain NULL streams. This allows + // the StreamTee to be used with hard coded indexes for clients + // that might want N total streams with only a few that are set + // to valid values. + Stream *strm = pos->get(); + if (strm) + strm->Flush (); + } + } + + virtual size_t + Write (const void *s, size_t length) + { + Mutex::Locker locker (m_streams_mutex); + if (m_streams.empty()) + return 0; + + size_t min_bytes_written = SIZE_MAX; + collection::iterator pos, end; + for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) + { + // Allow for our collection to contain NULL streams. This allows + // the StreamTee to be used with hard coded indexes for clients + // that might want N total streams with only a few that are set + // to valid values. + Stream *strm = pos->get(); + if (strm) + { + const size_t bytes_written = strm->Write (s, length); + if (min_bytes_written > bytes_written) + min_bytes_written = bytes_written; + } + } + if (min_bytes_written == SIZE_MAX) + return 0; + return min_bytes_written; + } + + size_t + AppendStream (const lldb::StreamSP &stream_sp) + { + size_t new_idx = m_streams.size(); + Mutex::Locker locker (m_streams_mutex); + m_streams.push_back (stream_sp); + return new_idx; + } + + size_t + GetNumStreams () const + { + size_t result = 0; + { + Mutex::Locker locker (m_streams_mutex); + result = m_streams.size(); + } + return result; + } + + lldb::StreamSP + GetStreamAtIndex (uint32_t idx) + { + lldb::StreamSP stream_sp; + Mutex::Locker locker (m_streams_mutex); + if (idx < m_streams.size()) + stream_sp = m_streams[idx]; + return stream_sp; + } + + void + SetStreamAtIndex (uint32_t idx, const lldb::StreamSP& stream_sp) + { + Mutex::Locker locker (m_streams_mutex); + // Resize our stream vector as necessary to fit as many streams + // as needed. This also allows this class to be used with hard + // coded indexes that can be used contain many streams, not all + // of which are valid. + if (idx >= m_streams.size()) + m_streams.resize(idx + 1); + m_streams[idx] = stream_sp; + } + + +protected: + typedef std::vector<lldb::StreamSP> collection; + mutable Mutex m_streams_mutex; + collection m_streams; +}; + +} // namespace lldb_private +#endif // #ifndef liblldb_StreamTee_h_ diff --git a/include/lldb/Core/StringList.h b/include/lldb/Core/StringList.h new file mode 100644 index 0000000..5503274 --- /dev/null +++ b/include/lldb/Core/StringList.h @@ -0,0 +1,107 @@ +//===-- StringList.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_StringList_h_ +#define liblldb_StringList_h_ + +#include <stdint.h> + +#include "lldb/Core/STLUtils.h" +#include "lldb/lldb-forward.h" + +namespace lldb_private { + +class StringList +{ +public: + + StringList (); + + StringList (const char *str); + + StringList (const char **strv, int strc); + + virtual + ~StringList (); + + void + AppendString (const std::string &s); + + void + AppendString (const char *str); + + void + AppendString (const char *str, size_t str_len); + + void + AppendList (const char ** strv, int strc); + + void + AppendList (StringList strings); + + bool + ReadFileLines (FileSpec &input_file); + + size_t + GetSize () const; + + const char * + GetStringAtIndex (size_t idx) const; + + void + Join (const char *separator, Stream &strm); + + void + Clear (); + + void + LongestCommonPrefix (std::string &common_prefix); + + void + InsertStringAtIndex (size_t id, const char *str); + + void + DeleteStringAtIndex (size_t id); + + void + RemoveBlankLines (); + + size_t + SplitIntoLines (const char *lines, size_t len); + + std::string + CopyList(const char* item_preamble = NULL, + const char* items_sep = "\n"); + + StringList& + operator << (const char* str); + + StringList& + operator << (StringList strings); + + // This string list contains a list of valid auto completion + // strings, and the "s" is passed in. "matches" is filled in + // with zero or more string values that start with "s", and + // the first string to exactly match one of the string + // values in this collection, will have "exact_matches_idx" + // filled in to match the index, or "exact_matches_idx" will + // have SIZE_MAX + size_t + AutoComplete (const char *s, + StringList &matches, + size_t &exact_matches_idx) const; + +private: + + STLStringArray m_strings; +}; + +} // namespace lldb_private + +#endif // liblldb_StringList_h_ diff --git a/include/lldb/Core/ThreadSafeSTLMap.h b/include/lldb/Core/ThreadSafeSTLMap.h new file mode 100644 index 0000000..703ce48 --- /dev/null +++ b/include/lldb/Core/ThreadSafeSTLMap.h @@ -0,0 +1,184 @@ +//===-- ThreadSafeSTLMap.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_ThreadSafeSTLMap_h_ +#define liblldb_ThreadSafeSTLMap_h_ + +// C Includes +// C++ Includes +#include <map> + +// Other libraries and framework includes +// Project includes +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +template <typename _Key, typename _Tp> +class ThreadSafeSTLMap +{ +public: + typedef std::map<_Key,_Tp> collection; + typedef typename collection::iterator iterator; + typedef typename collection::const_iterator const_iterator; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ThreadSafeSTLMap() : + m_collection (), + m_mutex (Mutex::eMutexTypeRecursive) + { + } + + ~ThreadSafeSTLMap() + { + } + + bool + IsEmpty() const + { + Mutex::Locker locker(m_mutex); + return m_collection.empty(); + } + + void + Clear() + { + Mutex::Locker locker(m_mutex); + return m_collection.clear(); + } + + size_t + Erase (const _Key& key) + { + Mutex::Locker locker(m_mutex); + return EraseNoLock (key); + } + + size_t + EraseNoLock (const _Key& key) + { + return m_collection.erase (key); + } + + bool + GetValueForKey (const _Key& key, _Tp &value) const + { + Mutex::Locker locker(m_mutex); + return GetValueForKeyNoLock (key, value); + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + bool + GetValueForKeyNoLock (const _Key& key, _Tp &value) const + { + const_iterator pos = m_collection.find(key); + if (pos != m_collection.end()) + { + value = pos->second; + return true; + } + return false; + } + + bool + GetFirstKeyForValue (const _Tp &value, _Key& key) const + { + Mutex::Locker locker(m_mutex); + return GetFirstKeyForValueNoLock (value, key); + } + + bool + GetFirstKeyForValueNoLock (const _Tp &value, _Key& key) const + { + const_iterator pos, end = m_collection.end(); + for (pos = m_collection.begin(); pos != end; ++pos) + { + if (pos->second == value) + { + key = pos->first; + return true; + } + } + return false; + } + + bool + LowerBound (const _Key& key, + _Key& match_key, + _Tp &match_value, + bool decrement_if_not_equal) const + { + Mutex::Locker locker(m_mutex); + return LowerBoundNoLock (key, match_key, match_value, decrement_if_not_equal); + } + + bool + LowerBoundNoLock (const _Key& key, + _Key& match_key, + _Tp &match_value, + bool decrement_if_not_equal) const + { + const_iterator pos = m_collection.lower_bound (key); + if (pos != m_collection.end()) + { + match_key = pos->first; + if (decrement_if_not_equal && key != match_key && pos != m_collection.begin()) + { + --pos; + match_key = pos->first; + } + match_value = pos->second; + return true; + } + return false; + } + + iterator + lower_bound_unsafe (const _Key& key) + { + return m_collection.lower_bound (key); + } + + void + SetValueForKey (const _Key& key, const _Tp &value) + { + Mutex::Locker locker(m_mutex); + SetValueForKeyNoLock (key, value); + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + void + SetValueForKeyNoLock (const _Key& key, const _Tp &value) + { + m_collection[key] = value; + } + + Mutex & + GetMutex () + { + return m_mutex; + } + +private: + collection m_collection; + mutable Mutex m_mutex; + + //------------------------------------------------------------------ + // For ThreadSafeSTLMap only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ThreadSafeSTLMap); +}; + + +} // namespace lldb_private + +#endif // liblldb_ThreadSafeSTLMap_h_ diff --git a/include/lldb/Core/ThreadSafeValue.h b/include/lldb/Core/ThreadSafeValue.h new file mode 100644 index 0000000..42a5a5c --- /dev/null +++ b/include/lldb/Core/ThreadSafeValue.h @@ -0,0 +1,96 @@ +//===-- ThreadSafeValue.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_ThreadSafeValue_h_ +#define liblldb_ThreadSafeValue_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +template <class T> +class ThreadSafeValue +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ThreadSafeValue() : + m_value (), + m_mutex (Mutex::eMutexTypeRecursive) + { + } + + ThreadSafeValue(const T& value) : + m_value (value), + m_mutex (Mutex::eMutexTypeRecursive) + { + } + + ~ThreadSafeValue() + { + } + + T + GetValue () const + { + T value; + { + Mutex::Locker locker(m_mutex); + value = m_value; + } + return value; + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + const T& + GetValueNoLock () const + { + return m_value; + } + + void + SetValue (const T& value) + { + Mutex::Locker locker(m_mutex); + m_value = value; + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + void + SetValueNoLock (const T& value) + { + m_value = value; + } + + Mutex & + GetMutex () + { + return m_mutex; + } + +private: + T m_value; + mutable Mutex m_mutex; + + //------------------------------------------------------------------ + // For ThreadSafeValue only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ThreadSafeValue); +}; + + +} // namespace lldb_private +#endif // liblldb_ThreadSafeValue_h_ diff --git a/include/lldb/Core/Timer.h b/include/lldb/Core/Timer.h new file mode 100644 index 0000000..e354d91 --- /dev/null +++ b/include/lldb/Core/Timer.h @@ -0,0 +1,160 @@ +//===-- Timer.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_Timer_h_ +#define liblldb_Timer_h_ +#if defined(__cplusplus) + +#include <stdarg.h> +#include <stdio.h> +#include <string> +#include "lldb/lldb-private.h" +#include "lldb/Host/TimeValue.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Timer Timer.h "lldb/Core/Timer.h" +/// @brief A timer class that simplifies common timing metrics. +/// +/// A scoped timer class that allows a variety of pthread mutex +/// objects to have a mutex locked when a Timer::Locker +/// object is created, and unlocked when it goes out of scope or +/// when the Timer::Locker::Reset(pthread_mutex_t *) +/// is called. This provides an exception safe way to lock a mutex +/// in a scope. +//---------------------------------------------------------------------- + +class Timer +{ +public: + static void + Initialize (); + + //-------------------------------------------------------------- + /// Default constructor. + //-------------------------------------------------------------- + Timer(const char *category, const char *format, ...) __attribute__ ((format (printf, 3, 4))); + + //-------------------------------------------------------------- + /// Desstructor + //-------------------------------------------------------------- + ~Timer(); + + void + Dump (); + + static void + SetDisplayDepth (uint32_t depth); + + static void + SetQuiet (bool value); + + static void + DumpCategoryTimes (Stream *s); + + static void + ResetCategoryTimes (); + +protected: + + void + ChildStarted (const TimeValue& time); + + void + ChildStopped (const TimeValue& time); + + uint64_t + GetTotalElapsedNanoSeconds(); + + uint64_t + GetTimerElapsedNanoSeconds(); + + //-------------------------------------------------------------- + /// Member variables + //-------------------------------------------------------------- + const char *m_category; + TimeValue m_total_start; + TimeValue m_timer_start; + uint64_t m_total_ticks; // Total running time for this timer including when other timers below this are running + uint64_t m_timer_ticks; // Ticks for this timer that do not include when other timers below this one are running + static uint32_t g_depth; + static uint32_t g_display_depth; + static FILE * g_file; +private: + Timer(); + DISALLOW_COPY_AND_ASSIGN (Timer); +}; + +class IntervalTimer +{ +public: + IntervalTimer() : + m_start (TimeValue::Now()) + { + } + + ~IntervalTimer() + { + } + + uint64_t + GetElapsedNanoSeconds() const + { + return TimeValue::Now() - m_start; + } + + void + Reset () + { + m_start = TimeValue::Now(); + } + + int + PrintfElapsed (const char *format, ...) __attribute__ ((format (printf, 2, 3))) + { + TimeValue now (TimeValue::Now()); + const uint64_t elapsed_nsec = now - m_start; + const char *unit = NULL; + float elapsed_value; + if (elapsed_nsec < 1000) + { + unit = "ns"; + elapsed_value = (float)elapsed_nsec; + } + else if (elapsed_nsec < 1000000) + { + unit = "us"; + elapsed_value = (float)elapsed_nsec/1000.0f; + } + else if (elapsed_nsec < 1000000000) + { + unit = "ms"; + elapsed_value = (float)elapsed_nsec/1000000.0f; + } + else + { + unit = "sec"; + elapsed_value = (float)elapsed_nsec/1000000000.0f; + } + int result = printf ("%3.2f %s: ", elapsed_value, unit); + va_list args; + va_start (args, format); + result += vprintf (format, args); + va_end (args); + return result; + } +protected: + TimeValue m_start; +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // #ifndef liblldb_Timer_h_ diff --git a/include/lldb/Core/UUID.h b/include/lldb/Core/UUID.h new file mode 100644 index 0000000..fe72b8e --- /dev/null +++ b/include/lldb/Core/UUID.h @@ -0,0 +1,109 @@ +//===-- UUID.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_UUID_h_ +#define liblldb_UUID_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class UUID +{ +public: + // Most UUIDs are 16 bytes, but some Linux build-ids (SHA1) are 20. + typedef uint8_t ValueType[20]; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + UUID (); + UUID (const UUID& rhs); + UUID (const void *uuid_bytes, uint32_t num_uuid_bytes); + + ~UUID (); + + const UUID& + operator=(const UUID& rhs); + + void + Clear (); + + void + Dump (Stream *s) const; + + const void * + GetBytes() const; + + size_t + GetByteSize(); + + bool + IsValid () const; + + bool + SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes = 16); + + std::string + GetAsString (const char *separator = NULL) const; + + size_t + SetFromCString (const char *c_str, uint32_t num_uuid_bytes = 16); + + // Decode as many UUID bytes (up to 16) as possible from the C string "cstr" + // This is used for auto completion where a partial UUID might have been + // typed in. It + //------------------------------------------------------------------ + /// Decode as many UUID bytes (up to 16) as possible from the C + /// string \a cstr. + /// + /// @param[in] cstr + /// A NULL terminate C string that points at a UUID string value + /// (no leading spaces). The string must contain only hex + /// characters and optionally can contain the '-' sepearators. + /// + /// @param[in] uuid_bytes + /// A buffer of bytes that will contain a full or patially + /// decoded UUID. + /// + /// @param[out] end + /// If \a end is not NULL, it will be filled in with the a + /// pointer to the character after the last successfully decoded + /// byte. + /// + /// @return + /// Returns the number of bytes that were successfully decoded + /// which should be 16 if a full UUID value was properly decoded. + //------------------------------------------------------------------ + static size_t + DecodeUUIDBytesFromCString (const char *cstr, ValueType &uuid_bytes, const char **end, uint32_t num_uuid_bytes = 16); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from UUID can see and modify these + //------------------------------------------------------------------ + uint32_t m_num_uuid_bytes; // Should be 16 or 20 + ValueType m_uuid; +}; + +bool operator == (const UUID &lhs, const UUID &rhs); +bool operator != (const UUID &lhs, const UUID &rhs); +bool operator < (const UUID &lhs, const UUID &rhs); +bool operator <= (const UUID &lhs, const UUID &rhs); +bool operator > (const UUID &lhs, const UUID &rhs); +bool operator >= (const UUID &lhs, const UUID &rhs); + +} // namespace lldb_private + +#endif // liblldb_UUID_h_ diff --git a/include/lldb/Core/UniqueCStringMap.h b/include/lldb/Core/UniqueCStringMap.h new file mode 100644 index 0000000..972c0d5 --- /dev/null +++ b/include/lldb/Core/UniqueCStringMap.h @@ -0,0 +1,361 @@ +//===-- UniqueCStringMap.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_UniqueCStringMap_h_ +#define liblldb_UniqueCStringMap_h_ +#if defined(__cplusplus) + +#include <assert.h> +#include <algorithm> +#include <vector> + +#include "lldb/Core/RegularExpression.h" + +namespace lldb_private { + + + +//---------------------------------------------------------------------- +// Templatized uniqued string map. +// +// This map is useful for mapping unique C string names to values of +// type T. Each "const char *" name added must be unique for a given +// C string value. ConstString::GetCString() can provide such strings. +// Any other string table that has guaranteed unique values can also +// be used. +//---------------------------------------------------------------------- +template <typename T> +class UniqueCStringMap +{ +public: + struct Entry + { + Entry () : + cstring(NULL), + value() + { + } + + Entry (const char *cstr) : + cstring(cstr), + value() + { + } + + Entry (const char *cstr, const T&v) : + cstring(cstr), + value(v) + { + } + + bool + operator < (const Entry& rhs) const + { + return cstring < rhs.cstring; + } + + const char* cstring; + T value; + }; + + //------------------------------------------------------------------ + // Call this function multiple times to add a bunch of entries to + // this map, then later call UniqueCStringMap<T>::Sort() before doing + // any searches by name. + //------------------------------------------------------------------ + void + Append (const char *unique_cstr, const T& value) + { + m_map.push_back (typename UniqueCStringMap<T>::Entry(unique_cstr, value)); + } + + void + Append (const Entry &e) + { + m_map.push_back (e); + } + + void + Clear () + { + m_map.clear(); + } + + //------------------------------------------------------------------ + // Call this function to always keep the map sorted when putting + // entries into the map. + //------------------------------------------------------------------ + void + Insert (const char *unique_cstr, const T& value) + { + typename UniqueCStringMap<T>::Entry e(unique_cstr, value); + m_map.insert (std::upper_bound (m_map.begin(), m_map.end(), e), e); + } + + void + Insert (const Entry &e) + { + m_map.insert (std::upper_bound (m_map.begin(), m_map.end(), e), e); + } + + //------------------------------------------------------------------ + // Get an entries by index in a variety of forms. + // + // The caller is responsible for ensuring that the collection does + // not change during while using the returned values. + //------------------------------------------------------------------ + bool + GetValueAtIndex (uint32_t idx, T &value) const + { + if (idx < m_map.size()) + { + value = m_map[idx].value; + return true; + } + return false; + } + + const char * + GetCStringAtIndexUnchecked (uint32_t idx) const + { + return m_map[idx].cstring; + } + + // Use this function if you have simple types in your map that you + // can easily copy when accessing values by index. + T + GetValueAtIndexUnchecked (uint32_t idx) const + { + return m_map[idx].value; + } + + // Use this function if you have complex types in your map that you + // don't want to copy when accessing values by index. + const T & + GetValueRefAtIndexUnchecked (uint32_t idx) const + { + return m_map[idx].value; + } + + const char * + GetCStringAtIndex (uint32_t idx) const + { + if (idx < m_map.size()) + return m_map[idx].cstring; + return NULL; + } + + //------------------------------------------------------------------ + // Find the value for the unique string in the map. + // + // Return the value for \a unique_cstr if one is found, return + // \a fail_value otherwise. This method works well for simple type + // T values and only if there is a sensible failure value that can + // be returned and that won't match any existing values. + //------------------------------------------------------------------ + T + Find (const char *unique_cstr, T fail_value) const + { + Entry search_entry (unique_cstr); + const_iterator end = m_map.end(); + const_iterator pos = std::lower_bound (m_map.begin(), end, search_entry); + if (pos != end) + { + if (pos->cstring == unique_cstr) + return pos->value; + } + return fail_value; + } + //------------------------------------------------------------------ + // Get a pointer to the first entry that matches "name". NULL will + // be returned if there is no entry that matches "name". + // + // The caller is responsible for ensuring that the collection does + // not change during while using the returned pointer. + //------------------------------------------------------------------ + const Entry * + FindFirstValueForName (const char *unique_cstr) const + { + Entry search_entry (unique_cstr); + const_iterator end = m_map.end(); + const_iterator pos = std::lower_bound (m_map.begin(), end, search_entry); + if (pos != end) + { + const char *pos_cstr = pos->cstring; + if (pos_cstr == unique_cstr) + return &(*pos); + } + return NULL; + } + + //------------------------------------------------------------------ + // Get a pointer to the next entry that matches "name" from a + // previously returned Entry pointer. NULL will be returned if there + // is no subsequent entry that matches "name". + // + // The caller is responsible for ensuring that the collection does + // not change during while using the returned pointer. + //------------------------------------------------------------------ + const Entry * + FindNextValueForName (const Entry *entry_ptr) const + { + if (!m_map.empty()) + { + const Entry *first_entry = &m_map[0]; + const Entry *after_last_entry = first_entry + m_map.size(); + const Entry *next_entry = entry_ptr + 1; + if (first_entry <= next_entry && next_entry < after_last_entry) + { + if (next_entry->cstring == entry_ptr->cstring) + return next_entry; + } + } + return NULL; + } + + size_t + GetValues (const char *unique_cstr, std::vector<T> &values) const + { + const size_t start_size = values.size(); + + Entry search_entry (unique_cstr); + const_iterator pos, end = m_map.end(); + for (pos = std::lower_bound (m_map.begin(), end, search_entry); pos != end; ++pos) + { + if (pos->cstring == unique_cstr) + values.push_back (pos->value); + else + break; + } + + return values.size() - start_size; + } + + size_t + GetValues (const RegularExpression& regex, std::vector<T> &values) const + { + const size_t start_size = values.size(); + + const_iterator pos, end = m_map.end(); + for (pos = m_map.begin(); pos != end; ++pos) + { + if (regex.Execute(pos->cstring)) + values.push_back (pos->value); + } + + return values.size() - start_size; + } + + //------------------------------------------------------------------ + // Get the total number of entries in this map. + //------------------------------------------------------------------ + size_t + GetSize () const + { + return m_map.size(); + } + + + //------------------------------------------------------------------ + // Returns true if this map is empty. + //------------------------------------------------------------------ + bool + IsEmpty() const + { + return m_map.empty(); + } + + //------------------------------------------------------------------ + // Reserve memory for at least "n" entries in the map. This is + // useful to call when you know you will be adding a lot of entries + // using UniqueCStringMap::Append() (which should be followed by a + // call to UniqueCStringMap::Sort()) or to UniqueCStringMap::Insert(). + //------------------------------------------------------------------ + void + Reserve (size_t n) + { + m_map.reserve (n); + } + + //------------------------------------------------------------------ + // Sort the unsorted contents in this map. A typical code flow would + // be: + // size_t approximate_num_entries = .... + // UniqueCStringMap<uint32_t> my_map; + // my_map.Reserve (approximate_num_entries); + // for (...) + // { + // my_map.Append (UniqueCStringMap::Entry(GetName(...), GetValue(...))); + // } + // my_map.Sort(); + //------------------------------------------------------------------ + void + Sort () + { + std::sort (m_map.begin(), m_map.end()); + } + + //------------------------------------------------------------------ + // Since we are using a vector to contain our items it will always + // double its memory consumption as things are added to the vector, + // so if you intend to keep a UniqueCStringMap around and have + // a lot of entries in the map, you will want to call this function + // to create a new vector and copy _only_ the exact size needed as + // part of the finalization of the string map. + //------------------------------------------------------------------ + void + SizeToFit () + { + if (m_map.size() < m_map.capacity()) + { + collection temp (m_map.begin(), m_map.end()); + m_map.swap(temp); + } + } + + size_t + Erase (const char *unique_cstr) + { + size_t num_removed = 0; + Entry search_entry (unique_cstr); + iterator end = m_map.end(); + iterator begin = m_map.begin(); + iterator lower_pos = std::lower_bound (begin, end, search_entry); + if (lower_pos != end) + { + if (lower_pos->cstring == unique_cstr) + { + iterator upper_pos = std::upper_bound (lower_pos, end, search_entry); + if (lower_pos == upper_pos) + { + m_map.erase (lower_pos); + num_removed = 1; + } + else + { + num_removed = std::distance (lower_pos, upper_pos); + m_map.erase (lower_pos, upper_pos); + } + } + } + return num_removed; + } +protected: + typedef std::vector<Entry> collection; + typedef typename collection::iterator iterator; + typedef typename collection::const_iterator const_iterator; + collection m_map; +}; + + + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_UniqueCStringMap_h_ diff --git a/include/lldb/Core/UserID.h b/include/lldb/Core/UserID.h new file mode 100644 index 0000000..ea6af74 --- /dev/null +++ b/include/lldb/Core/UserID.h @@ -0,0 +1,130 @@ +//===-- UserID.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_UserID_h_ +#define liblldb_UserID_h_ + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class UserID UserID.h "lldb/Core/UserID.h" +/// @brief A mix in class that contains a generic user ID. +/// +/// UserID is desinged as a mix in class that can contain an integer +/// based unique identifier for a varietly of objects in lldb. +/// +/// The value for this identifier is chosen by each parser plug-in. A +/// value should be chosen that makes sense for each kind of object +/// should and allows quick access to further and more in depth parsing. +/// +/// Symbol table entries can use this to store the original symbol table +/// index, functions can use it to store the symbol table index or the +/// DWARF offset. +//---------------------------------------------------------------------- +struct UserID +{ + //------------------------------------------------------------------ + /// Construct with optional user ID. + //------------------------------------------------------------------ + UserID (lldb::user_id_t uid = LLDB_INVALID_UID) : m_uid(uid) {} + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~UserID () + { + } + + //------------------------------------------------------------------ + /// Clears the object state. + /// + /// Clears the object contents back to a default invalid state. + //------------------------------------------------------------------ + void + Clear () { m_uid = LLDB_INVALID_UID; } + + //------------------------------------------------------------------ + /// Get accessor for the user ID. + /// + /// @return + /// The user ID. + //------------------------------------------------------------------ + lldb::user_id_t + GetID () const { return m_uid; } + + //------------------------------------------------------------------ + /// Set accessor for the user ID. + /// + /// @param[in] uid + /// The new user ID. + //------------------------------------------------------------------ + void + SetID (lldb::user_id_t uid) { m_uid = uid; } + + //------------------------------------------------------------------ + /// Unary predicate function object that can search for a matching + /// user ID. + /// + /// Function object that can be used on any class that inherits + /// from UserID: + /// \code + /// iterator pos; + /// pos = std::find_if (coll.begin(), coll.end(), UserID::IDMatches(blockID)); + /// \endcode + //------------------------------------------------------------------ + class IDMatches + { + public: + //-------------------------------------------------------------- + /// Construct with the user ID to look for. + //-------------------------------------------------------------- + IDMatches (lldb::user_id_t uid) : m_uid(uid) {} + + //-------------------------------------------------------------- + /// Unary predicate function object callback. + //-------------------------------------------------------------- + bool + operator () (const UserID& rhs) const { return m_uid == rhs.GetID(); } + + private: + //-------------------------------------------------------------- + // Member variables. + //-------------------------------------------------------------- + const lldb::user_id_t m_uid; ///< The user ID we are looking for + }; + + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + lldb::user_id_t m_uid; ///< The user ID that uniquely identifies an object. +}; + +inline bool operator== (const UserID& lhs, const UserID& rhs) +{ + return lhs.GetID() == rhs.GetID(); +} + +inline bool operator!= (const UserID& lhs, const UserID& rhs) +{ + return lhs.GetID() != rhs.GetID(); +} + +//-------------------------------------------------------------- +/// Stream the UserID object to a Stream. +//-------------------------------------------------------------- +Stream& operator << (Stream& strm, const UserID& uid); + +} // namespace lldb_private + +#endif // liblldb_UserID_h_ diff --git a/include/lldb/Core/UserSettingsController.h b/include/lldb/Core/UserSettingsController.h new file mode 100644 index 0000000..7e72b89 --- /dev/null +++ b/include/lldb/Core/UserSettingsController.h @@ -0,0 +1,98 @@ +//====-- UserSettingsController.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_UserSettingsController_h_ +#define liblldb_UserSettingsController_h_ + +// C Includes +// C++ Includes + +#include <string> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/StringList.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class Properties +{ +public: + Properties () : + m_collection_sp () + { + } + + Properties (const lldb::OptionValuePropertiesSP &collection_sp) : + m_collection_sp (collection_sp) + { + } + + virtual + ~Properties() + { + } + + virtual lldb::OptionValuePropertiesSP + GetValueProperties () const + { + // This function is virtual in case subclasses want to lazily + // implement creating the properties. + return m_collection_sp; + } + + virtual lldb::OptionValueSP + GetPropertyValue (const ExecutionContext *exe_ctx, + const char *property_path, + bool will_modify, + Error &error) const; + + virtual Error + SetPropertyValue (const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *property_path, + const char *value); + + virtual Error + DumpPropertyValue (const ExecutionContext *exe_ctx, + Stream &strm, + const char *property_path, + uint32_t dump_mask); + + virtual void + DumpAllPropertyValues (const ExecutionContext *exe_ctx, + Stream &strm, + uint32_t dump_mask); + + virtual void + DumpAllDescriptions (CommandInterpreter &interpreter, + Stream &strm) const; + + size_t + Apropos (const char *keyword, + std::vector<const Property *> &matching_properties) const; + + lldb::OptionValuePropertiesSP + GetSubProperty (const ExecutionContext *exe_ctx, + const ConstString &name); +protected: + lldb::OptionValuePropertiesSP m_collection_sp; +}; + +} // namespace lldb_private + +#endif // liblldb_UserSettingsController_h_ diff --git a/include/lldb/Core/VMRange.h b/include/lldb/Core/VMRange.h new file mode 100644 index 0000000..94c83e7 --- /dev/null +++ b/include/lldb/Core/VMRange.h @@ -0,0 +1,181 @@ +//===-- VMRange.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_VMRange_h_ +#define liblldb_VMRange_h_ + +#include "lldb/lldb-private.h" +#include <vector> + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A vm address range. These can represent offsets ranges or actual +// addresses. +//---------------------------------------------------------------------- +class VMRange +{ +public: + + typedef std::vector<VMRange> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + VMRange() : + m_base_addr(0), + m_byte_size(0) + { + } + + VMRange(lldb::addr_t start_addr, lldb::addr_t end_addr) : + m_base_addr(start_addr), + m_byte_size(end_addr > start_addr ? end_addr - start_addr : 0) + { + } + + ~VMRange() + { + } + + void + Clear () + { + m_base_addr = 0; + m_byte_size = 0; + } + + // Set the start and end values + void + Reset (lldb::addr_t start_addr, lldb::addr_t end_addr) + { + SetBaseAddress (start_addr); + SetEndAddress (end_addr); + } + + // Set the start value for the range, and keep the same size + void + SetBaseAddress (lldb::addr_t base_addr) + { + m_base_addr = base_addr; + } + + void + SetEndAddress (lldb::addr_t end_addr) + { + const lldb::addr_t base_addr = GetBaseAddress(); + if (end_addr > base_addr) + m_byte_size = end_addr - base_addr; + else + m_byte_size = 0; + } + + lldb::addr_t + GetByteSize () const + { + return m_byte_size; + } + + void + SetByteSize (lldb::addr_t byte_size) + { + m_byte_size = byte_size; + } + + lldb::addr_t + GetBaseAddress () const + { + return m_base_addr; + } + + lldb::addr_t + GetEndAddress () const + { + return GetBaseAddress() + m_byte_size; + } + + bool + IsValid() const + { + return m_byte_size > 0; + } + + bool + Contains (lldb::addr_t addr) const + { + return (GetBaseAddress() <= addr) && (addr < GetEndAddress()); + } + + bool + Contains (const VMRange& range) const + { + if (Contains(range.GetBaseAddress())) + { + lldb::addr_t range_end = range.GetEndAddress(); + return (GetBaseAddress() <= range_end) && (range_end <= GetEndAddress()); + } + return false; + } + + void + Dump (Stream *s, lldb::addr_t base_addr = 0, uint32_t addr_width = 8) const; + + class ValueInRangeUnaryPredicate + { + public: + ValueInRangeUnaryPredicate(lldb::addr_t value) : + _value(value) + { + } + bool operator()(const VMRange& range) const + { + return range.Contains(_value); + } + lldb::addr_t _value; + }; + + class RangeInRangeUnaryPredicate + { + public: + RangeInRangeUnaryPredicate(VMRange range) : + _range(range) + { + } + bool operator()(const VMRange& range) const + { + return range.Contains(_range); + } + const VMRange& _range; + }; + + static bool + ContainsValue(const VMRange::collection& coll, lldb::addr_t value); + + static bool + ContainsRange(const VMRange::collection& coll, const VMRange& range); + + // Returns a valid index into coll when a match is found, else UINT32_MAX + // is returned + static size_t + FindRangeIndexThatContainsValue (const VMRange::collection& coll, lldb::addr_t value); + +protected: + lldb::addr_t m_base_addr; + lldb::addr_t m_byte_size; +}; + +bool operator== (const VMRange& lhs, const VMRange& rhs); +bool operator!= (const VMRange& lhs, const VMRange& rhs); +bool operator< (const VMRange& lhs, const VMRange& rhs); +bool operator<= (const VMRange& lhs, const VMRange& rhs); +bool operator> (const VMRange& lhs, const VMRange& rhs); +bool operator>= (const VMRange& lhs, const VMRange& rhs); + +} // namespace lldb_private + +#endif // liblldb_VMRange_h_ diff --git a/include/lldb/Core/Value.h b/include/lldb/Core/Value.h new file mode 100644 index 0000000..5461ca7 --- /dev/null +++ b/include/lldb/Core/Value.h @@ -0,0 +1,314 @@ +//===-- Value.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_Value_h_ +#define liblldb_Value_h_ + +// C Includes +// C++ Includes +#include <string> +#include <vector> +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Symbol/ClangASTType.h" + +namespace lldb_private { + +class Value +{ +public: + + // Values Less than zero are an error, greater than or equal to zero + // returns what the Scalar result is. + enum ValueType + { + // m_value contains... + // ============================ + eValueTypeScalar, // raw scalar value + eValueTypeVector, // byte array of m_vector.length with endianness of m_vector.byte_order + eValueTypeFileAddress, // file address value + eValueTypeLoadAddress, // load address value + eValueTypeHostAddress // host address value (for memory in the process that is using liblldb) + }; + + enum ContextType // Type that describes Value::m_context + { + // m_context contains... + // ==================== + eContextTypeInvalid, // undefined + eContextTypeRegisterInfo, // RegisterInfo * (can be a scalar or a vector register) + eContextTypeLLDBType, // lldb_private::Type * + eContextTypeVariable // lldb_private::Variable * + }; + + const static size_t kMaxByteSize = 32u; + + struct Vector + { + // The byte array must be big enough to hold vector registers for any supported target. + uint8_t bytes[kMaxByteSize]; + size_t length; + lldb::ByteOrder byte_order; + + Vector() : + length(0), + byte_order(lldb::eByteOrderInvalid) + { + } + + Vector(const Vector& vector) + { *this = vector; + } + const Vector& + operator=(const Vector& vector) + { + SetBytes(vector.bytes, vector.length, vector.byte_order); + return *this; + } + + void + Clear () + { + length = 0; + } + + bool + SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order) + { + this->length = length; + this->byte_order = byte_order; + if (length) + ::memcpy(this->bytes, bytes, length < kMaxByteSize ? length : kMaxByteSize); + return IsValid(); + } + + bool + IsValid() const + { + return (length > 0 && length < kMaxByteSize && byte_order != lldb::eByteOrderInvalid); + } + // Casts a vector, if valid, to an unsigned int of matching or largest supported size. + // Truncates to the beginning of the vector if required. + // Returns a default constructed Scalar if the Vector data is internally inconsistent. + Scalar + GetAsScalar() const + { + Scalar scalar; + if (IsValid()) + { + if (length == 1) scalar = *(const uint8_t *)bytes; + else if (length == 2) scalar = *(const uint16_t *)bytes; + else if (length == 4) scalar = *(const uint32_t *)bytes; + else if (length == 8) scalar = *(const uint64_t *)bytes; +#if defined (ENABLE_128_BIT_SUPPORT) + else if (length >= 16) scalar = *(const __uint128_t *)bytes; +#else + else if (length >= 16) scalar = *(const __uint64_t *)bytes; +#endif + } + return scalar; + } + }; + + Value(); + Value(const Scalar& scalar); + Value(const Vector& vector); + Value(const uint8_t *bytes, int len); + Value(const Value &rhs); + + Value & + operator=(const Value &rhs); + + const ClangASTType & + GetClangType(); + + void + SetClangType (const ClangASTType &clang_type); + + ValueType + GetValueType() const; + + AddressType + GetValueAddressType () const; + + ContextType + GetContextType() const + { + return m_context_type; + } + + void + SetValueType (ValueType value_type) + { + m_value_type = value_type; + } + + void + ClearContext () + { + m_context = NULL; + m_context_type = eContextTypeInvalid; + } + + void + SetContext (ContextType context_type, void *p) + { + m_context_type = context_type; + m_context = p; + if (m_context_type == eContextTypeRegisterInfo) { + RegisterInfo *reg_info = GetRegisterInfo(); + if (reg_info->encoding == lldb::eEncodingVector) + SetValueType(eValueTypeVector); + else + SetValueType(eValueTypeScalar); + } + } + + RegisterInfo * + GetRegisterInfo() const; + + Type * + GetType(); + + Scalar & + ResolveValue (ExecutionContext *exe_ctx); + + const Scalar & + GetScalar() const + { + return m_value; + } + + const Vector & + GetVector() const + { + return m_vector; + } + + Scalar & + GetScalar() + { + return m_value; + } + + Vector & + GetVector() + { + return m_vector; + } + + bool + SetVectorBytes(const Vector& vector) + { + m_vector = vector; + return m_vector.IsValid(); + } + + bool + SetVectorBytes(uint8_t *bytes, size_t length, lldb::ByteOrder byte_order) + { + return m_vector.SetBytes(bytes, length, byte_order); + } + + bool + SetScalarFromVector() + { + if (m_vector.IsValid()) + { + m_value = m_vector.GetAsScalar(); + return true; + } + return false; + } + + void + ResizeData(size_t len); + + bool + ValueOf(ExecutionContext *exe_ctx); + + Variable * + GetVariable(); + + void + Dump (Stream* strm); + + lldb::Format + GetValueDefaultFormat (); + + uint64_t + GetValueByteSize (Error *error_ptr); + + Error + GetValueAsData (ExecutionContext *exe_ctx, + DataExtractor &data, + uint32_t data_offset, + Module *module); // Can be NULL + + static const char * + GetValueTypeAsCString (ValueType context_type); + + static const char * + GetContextTypeAsCString (ContextType context_type); + + bool + GetData (DataExtractor &data); + + void + Clear(); + +protected: + Scalar m_value; + Vector m_vector; + ClangASTType m_clang_type; + void * m_context; + ValueType m_value_type; + ContextType m_context_type; + DataBufferHeap m_data_buffer; +}; + +class ValueList +{ +public: + ValueList () : + m_values() + { + } + + ValueList (const ValueList &rhs); + + ~ValueList () + { + } + + const ValueList & operator= (const ValueList &rhs); + + // void InsertValue (Value *value, size_t idx); + void PushValue (const Value &value); + + size_t GetSize (); + Value *GetValueAtIndex(size_t idx); + void Clear(); + +protected: + +private: + typedef std::vector<Value> collection; + + collection m_values; +}; + +} // namespace lldb_private + +#endif // liblldb_Value_h_ diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h new file mode 100644 index 0000000..0d965d6 --- /dev/null +++ b/include/lldb/Core/ValueObject.h @@ -0,0 +1,1375 @@ +//===-- ValueObject.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_ValueObject_h_ +#define liblldb_ValueObject_h_ + +// C Includes +// C++ Includes +#include <initializer_list> +#include <map> +#include <vector> +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Flags.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/UserID.h" +#include "lldb/Core/Value.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackID.h" +#include "lldb/Utility/SharedCluster.h" + +namespace lldb_private { + +/// ValueObject: +/// +/// This abstract class provides an interface to a particular value, be it a register, a local or global variable, +/// that is evaluated in some particular scope. The ValueObject also has the capibility of being the "child" of +/// some other variable object, and in turn of having children. +/// If a ValueObject is a root variable object - having no parent - then it must be constructed with respect to some +/// particular ExecutionContextScope. If it is a child, it inherits the ExecutionContextScope from its parent. +/// The ValueObject will update itself if necessary before fetching its value, summary, object description, etc. +/// But it will always update itself in the ExecutionContextScope with which it was originally created. + +/// A brief note on life cycle management for ValueObjects. This is a little tricky because a ValueObject can contain +/// various other ValueObjects - the Dynamic Value, its children, the dereference value, etc. Any one of these can be +/// handed out as a shared pointer, but for that contained value object to be valid, the root object and potentially other +/// of the value objects need to stay around. +/// We solve this problem by handing out shared pointers to the Value Object and any of its dependents using a shared +/// ClusterManager. This treats each shared pointer handed out for the entire cluster as a reference to the whole +/// cluster. The whole cluster will stay around until the last reference is released. +/// +/// The ValueObject mostly handle this automatically, if a value object is made with a Parent ValueObject, then it adds +/// itself to the ClusterManager of the parent. + +/// It does mean that external to the ValueObjects we should only ever make available ValueObjectSP's, never ValueObjects +/// or pointers to them. So all the "Root level" ValueObject derived constructors should be private, and +/// should implement a Create function that new's up object and returns a Shared Pointer that it gets from the GetSP() method. +/// +/// However, if you are making an derived ValueObject that will be contained in a parent value object, you should just +/// hold onto a pointer to it internally, and by virtue of passing the parent ValueObject into its constructor, it will +/// be added to the ClusterManager for the parent. Then if you ever hand out a Shared Pointer to the contained ValueObject, +/// just do so by calling GetSP() on the contained object. + +class ValueObject : public UserID +{ +public: + + enum GetExpressionPathFormat + { + eGetExpressionPathFormatDereferencePointers = 1, + eGetExpressionPathFormatHonorPointers + }; + + enum ValueObjectRepresentationStyle + { + eValueObjectRepresentationStyleValue = 1, + eValueObjectRepresentationStyleSummary, + eValueObjectRepresentationStyleLanguageSpecific, + eValueObjectRepresentationStyleLocation, + eValueObjectRepresentationStyleChildrenCount, + eValueObjectRepresentationStyleType, + eValueObjectRepresentationStyleName, + eValueObjectRepresentationStyleExpressionPath + }; + + enum ExpressionPathScanEndReason + { + eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse + eExpressionPathScanEndReasonNoSuchChild, // child element not found + eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for arrays + eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be used + eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be used + eExpressionPathScanEndReasonFragileIVarNotAllowed, // ObjC ivar expansion not allowed + eExpressionPathScanEndReasonRangeOperatorNotAllowed, // [] not allowed by options + eExpressionPathScanEndReasonRangeOperatorInvalid, // [] not valid on objects other than scalars, pointers or arrays + eExpressionPathScanEndReasonArrayRangeOperatorMet, // [] is good for arrays, but I cannot parse it + eExpressionPathScanEndReasonBitfieldRangeOperatorMet, // [] is good for bitfields, but I cannot parse after it + eExpressionPathScanEndReasonUnexpectedSymbol, // something is malformed in the expression + eExpressionPathScanEndReasonTakingAddressFailed, // impossible to apply & operator + eExpressionPathScanEndReasonDereferencingFailed, // impossible to apply * operator + eExpressionPathScanEndReasonRangeOperatorExpanded, // [] was expanded into a VOList + eExpressionPathScanEndReasonSyntheticValueMissing, // getting the synthetic children failed + eExpressionPathScanEndReasonUnknown = 0xFFFF + }; + + enum ExpressionPathEndResultType + { + eExpressionPathEndResultTypePlain = 1, // anything but... + eExpressionPathEndResultTypeBitfield, // a bitfield + eExpressionPathEndResultTypeBoundedRange, // a range [low-high] + eExpressionPathEndResultTypeUnboundedRange, // a range [] + eExpressionPathEndResultTypeValueObjectList, // several items in a VOList + eExpressionPathEndResultTypeInvalid = 0xFFFF + }; + + enum ExpressionPathAftermath + { + eExpressionPathAftermathNothing = 1, // just return it + eExpressionPathAftermathDereference, // dereference the target + eExpressionPathAftermathTakeAddress // take target's address + }; + + enum ClearUserVisibleDataItems + { + eClearUserVisibleDataItemsNothing = 1u << 0, + eClearUserVisibleDataItemsValue = 1u << 1, + eClearUserVisibleDataItemsSummary = 1u << 2, + eClearUserVisibleDataItemsLocation = 1u << 3, + eClearUserVisibleDataItemsDescription = 1u << 4, + eClearUserVisibleDataItemsSyntheticChildren = 1u << 5, + eClearUserVisibleDataItemsAllStrings = eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary | eClearUserVisibleDataItemsLocation | eClearUserVisibleDataItemsDescription, + eClearUserVisibleDataItemsAll = 0xFFFF + }; + + struct GetValueForExpressionPathOptions + { + bool m_check_dot_vs_arrow_syntax; + bool m_no_fragile_ivar; + bool m_allow_bitfields_syntax; + bool m_no_synthetic_children; + + GetValueForExpressionPathOptions(bool dot = false, + bool no_ivar = false, + bool bitfield = true, + bool no_synth = false) : + m_check_dot_vs_arrow_syntax(dot), + m_no_fragile_ivar(no_ivar), + m_allow_bitfields_syntax(bitfield), + m_no_synthetic_children(no_synth) + { + } + + 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; + } + + GetValueForExpressionPathOptions& + DoAllowSyntheticChildren() + { + m_no_synthetic_children = false; + return *this; + } + + GetValueForExpressionPathOptions& + DontAllowSyntheticChildren() + { + m_no_synthetic_children = true; + return *this; + } + + static const GetValueForExpressionPathOptions + DefaultOptions() + { + static GetValueForExpressionPathOptions g_default_options; + + return g_default_options; + } + + }; + + struct DumpValueObjectOptions + { + uint32_t m_max_ptr_depth; + uint32_t m_max_depth; + bool m_show_types; + bool m_show_location; + bool m_use_objc; + lldb::DynamicValueType m_use_dynamic; + bool m_use_synthetic; + bool m_scope_already_checked; + bool m_flat_output; + uint32_t m_omit_summary_depth; + bool m_ignore_cap; + lldb::Format m_format; + lldb::TypeSummaryImplSP m_summary_sp; + std::string m_root_valobj_name; + bool m_hide_root_type; + bool m_hide_name; + bool m_hide_value; + + DumpValueObjectOptions() : + m_max_ptr_depth(0), + m_max_depth(UINT32_MAX), + m_show_types(false), + m_show_location(false), + m_use_objc(false), + m_use_dynamic(lldb::eNoDynamicValues), + m_use_synthetic(true), + m_scope_already_checked(false), + m_flat_output(false), + m_omit_summary_depth(0), + m_ignore_cap(false), + m_format (lldb::eFormatDefault), + m_summary_sp(), + m_root_valobj_name(), + m_hide_root_type(false), // provide a special compact display for "po" + m_hide_name(false), // provide a special compact display for "po" + m_hide_value(false) // provide a special compact display for "po" + {} + + static const DumpValueObjectOptions + DefaultOptions() + { + static DumpValueObjectOptions g_default_options; + + return g_default_options; + } + + DumpValueObjectOptions (const DumpValueObjectOptions& rhs) : + m_max_ptr_depth(rhs.m_max_ptr_depth), + m_max_depth(rhs.m_max_depth), + m_show_types(rhs.m_show_types), + m_show_location(rhs.m_show_location), + m_use_objc(rhs.m_use_objc), + m_use_dynamic(rhs.m_use_dynamic), + m_use_synthetic(rhs.m_use_synthetic), + m_scope_already_checked(rhs.m_scope_already_checked), + m_flat_output(rhs.m_flat_output), + m_omit_summary_depth(rhs.m_omit_summary_depth), + m_ignore_cap(rhs.m_ignore_cap), + m_format(rhs.m_format), + m_summary_sp(rhs.m_summary_sp), + m_root_valobj_name(rhs.m_root_valobj_name), + m_hide_root_type(rhs.m_hide_root_type), + m_hide_name(rhs.m_hide_name), + m_hide_value(rhs.m_hide_value) + {} + + DumpValueObjectOptions& + SetMaximumPointerDepth(uint32_t depth = 0) + { + m_max_ptr_depth = depth; + return *this; + } + + DumpValueObjectOptions& + SetMaximumDepth(uint32_t depth = 0) + { + m_max_depth = depth; + return *this; + } + + DumpValueObjectOptions& + SetShowTypes(bool show = false) + { + m_show_types = show; + return *this; + } + + DumpValueObjectOptions& + SetShowLocation(bool show = false) + { + m_show_location = show; + return *this; + } + + DumpValueObjectOptions& + SetUseObjectiveC(bool use = false) + { + m_use_objc = use; + return *this; + } + + DumpValueObjectOptions& + SetShowSummary(bool show = true) + { + if (show == false) + SetOmitSummaryDepth(UINT32_MAX); + else + SetOmitSummaryDepth(0); + return *this; + } + + DumpValueObjectOptions& + SetUseDynamicType(lldb::DynamicValueType dyn = lldb::eNoDynamicValues) + { + m_use_dynamic = dyn; + return *this; + } + + DumpValueObjectOptions& + SetUseSyntheticValue(bool use_synthetic = true) + { + m_use_synthetic = use_synthetic; + return *this; + } + + DumpValueObjectOptions& + SetScopeChecked(bool check = true) + { + m_scope_already_checked = check; + return *this; + } + + DumpValueObjectOptions& + SetFlatOutput(bool flat = false) + { + m_flat_output = flat; + return *this; + } + + DumpValueObjectOptions& + SetOmitSummaryDepth(uint32_t depth = 0) + { + m_omit_summary_depth = depth; + return *this; + } + + DumpValueObjectOptions& + SetIgnoreCap(bool ignore = false) + { + m_ignore_cap = ignore; + return *this; + } + + DumpValueObjectOptions& + SetRawDisplay(bool raw = false) + { + if (raw) + { + SetUseSyntheticValue(false); + SetOmitSummaryDepth(UINT32_MAX); + SetIgnoreCap(true); + SetHideName(false); + SetHideValue(false); + } + else + { + SetUseSyntheticValue(true); + SetOmitSummaryDepth(0); + SetIgnoreCap(false); + SetHideName(false); + SetHideValue(false); + } + return *this; + } + + DumpValueObjectOptions& + SetFormat (lldb::Format format = lldb::eFormatDefault) + { + m_format = format; + return *this; + } + + DumpValueObjectOptions& + SetSummary (lldb::TypeSummaryImplSP summary = lldb::TypeSummaryImplSP()) + { + m_summary_sp = summary; + return *this; + } + + DumpValueObjectOptions& + SetRootValueObjectName (const char* name = NULL) + { + if (name) + m_root_valobj_name.assign(name); + else + m_root_valobj_name.clear(); + return *this; + } + + DumpValueObjectOptions& + SetHideRootType (bool hide_root_type = false) + { + m_hide_root_type = hide_root_type; + return *this; + } + + DumpValueObjectOptions& + SetHideName (bool hide_name = false) + { + m_hide_name = hide_name; + return *this; + } + + DumpValueObjectOptions& + SetHideValue (bool hide_value = false) + { + m_hide_value = hide_value; + return *this; + } + }; + + class EvaluationPoint + { + public: + + EvaluationPoint (); + + EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected = false); + + EvaluationPoint (const EvaluationPoint &rhs); + + ~EvaluationPoint (); + + const ExecutionContextRef & + GetExecutionContextRef() const + { + return m_exe_ctx_ref; + } + + // Set the EvaluationPoint to the values in exe_scope, + // Return true if the Evaluation Point changed. + // Since the ExecutionContextScope is always going to be valid currently, + // the Updated Context will also always be valid. + +// bool +// SetContext (ExecutionContextScope *exe_scope); + + void + SetIsConstant () + { + SetUpdated(); + m_mod_id.SetInvalid(); + } + + bool + IsConstant () const + { + return !m_mod_id.IsValid(); + } + + ProcessModID + GetModID () const + { + return m_mod_id; + } + + void + SetUpdateID (ProcessModID new_id) + { + m_mod_id = new_id; + } + + bool + IsFirstEvaluation () const + { + return m_first_update; + } + + void + SetNeedsUpdate () + { + m_needs_update = true; + } + + void + SetUpdated (); + + bool + NeedsUpdating() + { + SyncWithProcessState(); + return m_needs_update; + } + + bool + IsValid () + { + if (!m_mod_id.IsValid()) + return false; + else if (SyncWithProcessState ()) + { + if (!m_mod_id.IsValid()) + return false; + } + return true; + } + + void + SetInvalid () + { + // Use the stop id to mark us as invalid, leave the thread id and the stack id around for logging and + // history purposes. + m_mod_id.SetInvalid(); + + // Can't update an invalid state. + m_needs_update = false; + + } + + private: + bool + SyncWithProcessState (); + + ProcessModID m_mod_id; // This is the stop id when this ValueObject was last evaluated. + ExecutionContextRef m_exe_ctx_ref; + bool m_needs_update; + bool m_first_update; + }; + + const EvaluationPoint & + GetUpdatePoint () const + { + return m_update_point; + } + + EvaluationPoint & + GetUpdatePoint () + { + return m_update_point; + } + + const ExecutionContextRef & + GetExecutionContextRef() const + { + return m_update_point.GetExecutionContextRef(); + } + + lldb::TargetSP + GetTargetSP() const + { + return m_update_point.GetExecutionContextRef().GetTargetSP(); + } + + lldb::ProcessSP + GetProcessSP() const + { + return m_update_point.GetExecutionContextRef().GetProcessSP(); + } + + lldb::ThreadSP + GetThreadSP() const + { + return m_update_point.GetExecutionContextRef().GetThreadSP(); + } + + lldb::StackFrameSP + GetFrameSP() const + { + return m_update_point.GetExecutionContextRef().GetFrameSP(); + } + + void + SetNeedsUpdate (); + + virtual ~ValueObject(); + + ClangASTType + GetClangType (); + + //------------------------------------------------------------------ + // Sublasses must implement the functions below. + //------------------------------------------------------------------ + virtual uint64_t + GetByteSize() = 0; + + virtual lldb::ValueType + GetValueType() const = 0; + + //------------------------------------------------------------------ + // Sublasses can implement the functions below. + //------------------------------------------------------------------ + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + + virtual lldb::LanguageType + GetObjectRuntimeLanguage(); + + virtual uint32_t + GetTypeInfo (ClangASTType *pointee_or_element_clang_type = NULL); + + virtual bool + IsPointerType (); + + virtual bool + IsArrayType (); + + virtual bool + IsScalarType (); + + virtual bool + IsPointerOrReferenceType (); + + virtual bool + IsPossibleDynamicType (); + + virtual bool + IsObjCNil (); + + virtual bool + IsBaseClass () + { + return false; + } + + virtual bool + IsDereferenceOfParent () + { + return false; + } + + bool + IsIntegerType (bool &is_signed); + + virtual bool + GetBaseClassPath (Stream &s); + + virtual void + GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers); + + 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); + + int + GetValuesForExpressionPath(const char* expression, + lldb::ValueObjectListSP& list, + 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 () + { + return true; + } + + virtual off_t + GetByteOffset() + { + return 0; + } + + virtual uint32_t + GetBitfieldBitSize () + { + return 0; + } + + virtual uint32_t + GetBitfieldBitOffset () + { + return 0; + } + + bool + IsBitfield () + { + return (GetBitfieldBitSize() != 0) || (GetBitfieldBitOffset() != 0); + } + + virtual bool + IsArrayItemForPointer() + { + return m_is_array_item_for_pointer; + } + + virtual const char * + GetValueAsCString (); + + virtual bool + GetValueAsCString (lldb::Format format, + std::string& destination); + + virtual uint64_t + GetValueAsUnsigned (uint64_t fail_value, bool *success = NULL); + + virtual bool + SetValueFromCString (const char *value_str, Error& error); + + // 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 lldb::ModuleSP + GetModule(); + + virtual ValueObject* + GetRoot (); + + virtual bool + GetDeclaration (Declaration &decl); + + //------------------------------------------------------------------ + // The functions below should NOT be modified by sublasses + //------------------------------------------------------------------ + const Error & + GetError(); + + const ConstString & + GetName() const; + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx, bool can_create); + + // this will always create the children if necessary + lldb::ValueObjectSP + GetChildAtIndexPath (const std::initializer_list<size_t> &idxs, + size_t* index_of_error = NULL); + + lldb::ValueObjectSP + GetChildAtIndexPath (const std::vector<size_t> &idxs, + size_t* index_of_error = NULL); + + lldb::ValueObjectSP + GetChildAtIndexPath (const std::initializer_list< std::pair<size_t, bool> > &idxs, + size_t* index_of_error = NULL); + + lldb::ValueObjectSP + GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs, + size_t* index_of_error = NULL); + + virtual lldb::ValueObjectSP + GetChildMemberWithName (const ConstString &name, bool can_create); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + size_t + GetNumChildren (); + + const Value & + GetValue() const; + + Value & + GetValue(); + + virtual bool + ResolveValue (Scalar &scalar); + + virtual const char * + GetLocationAsCString (); + + const char * + GetSummaryAsCString (); + + bool + GetSummaryAsCString (TypeSummaryImpl* summary_ptr, + std::string& destination); + + const char * + GetObjectDescription (); + + bool + HasSpecialPrintableRepresentation (ValueObjectRepresentationStyle val_obj_display, + lldb::Format custom_format); + + enum PrintableRepresentationSpecialCases + { + ePrintableRepresentationSpecialCasesDisable = 0, + ePrintableRepresentationSpecialCasesAllow = 1, + ePrintableRepresentationSpecialCasesOnly = 3 + }; + + bool + DumpPrintableRepresentation (Stream& s, + ValueObjectRepresentationStyle val_obj_display = eValueObjectRepresentationStyleSummary, + lldb::Format custom_format = lldb::eFormatInvalid, + PrintableRepresentationSpecialCases special = ePrintableRepresentationSpecialCasesAllow); + bool + GetValueIsValid () const; + + bool + GetValueDidChange (); + + bool + UpdateValueIfNeeded (bool update_format = true); + + bool + UpdateFormatsIfNeeded(); + + lldb::ValueObjectSP + GetSP () + { + return m_manager->GetSharedPointer(this); + } + + void + SetName (const ConstString &name); + + virtual lldb::addr_t + GetAddressOf (bool scalar_is_load_address = true, + AddressType *address_type = NULL); + + lldb::addr_t + GetPointerValue (AddressType *address_type = NULL); + + lldb::ValueObjectSP + GetSyntheticChild (const ConstString &key) const; + + lldb::ValueObjectSP + GetSyntheticArrayMember (size_t index, bool can_create); + + lldb::ValueObjectSP + GetSyntheticArrayMemberFromPointer (size_t index, bool can_create); + + lldb::ValueObjectSP + GetSyntheticArrayMemberFromArray (size_t index, bool can_create); + + lldb::ValueObjectSP + GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create); + + lldb::ValueObjectSP + GetSyntheticExpressionPathChild(const char* expression, bool can_create); + + virtual lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + + virtual lldb::ValueObjectSP + GetDynamicValue (lldb::DynamicValueType valueType); + + lldb::DynamicValueType + GetDynamicValueType (); + + virtual lldb::ValueObjectSP + GetStaticValue (); + + virtual lldb::ValueObjectSP + GetNonSyntheticValue (); + + lldb::ValueObjectSP + GetSyntheticValue (bool use_synthetic = true); + + virtual bool + HasSyntheticValue(); + + virtual bool + IsSynthetic() { return false; } + + virtual lldb::ValueObjectSP + CreateConstantValue (const ConstString &name); + + virtual lldb::ValueObjectSP + Dereference (Error &error); + + virtual lldb::ValueObjectSP + AddressOf (Error &error); + + virtual lldb::addr_t + GetLiveAddress() + { + return LLDB_INVALID_ADDRESS; + } + + virtual void + SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, + AddressType address_type = eAddressTypeLoad) + { + } + + virtual lldb::ValueObjectSP + Cast (const ClangASTType &clang_ast_type); + + virtual lldb::ValueObjectSP + CastPointerType (const char *name, + ClangASTType &ast_type); + + virtual lldb::ValueObjectSP + CastPointerType (const char *name, + lldb::TypeSP &type_sp); + + // The backing bits of this value object were updated, clear any + // descriptive string, so we know we have to refetch them + virtual void + ValueUpdated () + { + ClearUserVisibleData(eClearUserVisibleDataItemsValue | + eClearUserVisibleDataItemsSummary | + eClearUserVisibleDataItemsDescription); + } + + virtual bool + IsDynamic () + { + return false; + } + + virtual SymbolContextScope * + GetSymbolContextScope(); + + static void + DumpValueObject (Stream &s, + ValueObject *valobj); + static void + DumpValueObject (Stream &s, + ValueObject *valobj, + const DumpValueObjectOptions& options); + + static lldb::ValueObjectSP + CreateValueObjectFromExpression (const char* name, + const char* expression, + const ExecutionContext& exe_ctx); + + static lldb::ValueObjectSP + CreateValueObjectFromAddress (const char* name, + uint64_t address, + const ExecutionContext& exe_ctx, + ClangASTType type); + + static lldb::ValueObjectSP + CreateValueObjectFromData (const char* name, + DataExtractor& data, + const ExecutionContext& exe_ctx, + ClangASTType type); + + static void + LogValueObject (Log *log, + ValueObject *valobj); + + static void + LogValueObject (Log *log, + ValueObject *valobj, + const DumpValueObjectOptions& options); + + + // returns true if this is a char* or a char[] + // if it is a char* and check_pointer is true, + // it also checks that the pointer is valid + bool + IsCStringContainer (bool check_pointer = false); + + size_t + ReadPointedString (Stream& s, + Error& error, + uint32_t max_length = 0, + bool honor_array = true, + lldb::Format item_format = lldb::eFormatCharArray); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + + virtual uint64_t + GetData (DataExtractor& data); + + virtual bool + SetData (DataExtractor &data, Error &error); + + bool + GetIsConstant () const + { + return m_update_point.IsConstant(); + } + + void + SetIsConstant () + { + m_update_point.SetIsConstant(); + } + + lldb::Format + GetFormat () const; + + void + SetFormat (lldb::Format format) + { + if (format != m_format) + ClearUserVisibleData(eClearUserVisibleDataItemsValue); + m_format = format; + } + + lldb::TypeSummaryImplSP + GetSummaryFormat() + { + UpdateFormatsIfNeeded(); + return m_type_summary_sp; + } + + void + SetSummaryFormat(lldb::TypeSummaryImplSP format) + { + m_type_summary_sp = format; + ClearUserVisibleData(eClearUserVisibleDataItemsSummary); + } + + void + SetValueFormat(lldb::TypeFormatImplSP format) + { + m_type_format_sp = format; + ClearUserVisibleData(eClearUserVisibleDataItemsValue); + } + + lldb::TypeFormatImplSP + GetValueFormat() + { + UpdateFormatsIfNeeded(); + return m_type_format_sp; + } + + void + SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) + { + if (synth_sp.get() == m_synthetic_children_sp.get()) + return; + ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren); + m_synthetic_children_sp = synth_sp; + } + + lldb::SyntheticChildrenSP + GetSyntheticChildren() + { + UpdateFormatsIfNeeded(); + return m_synthetic_children_sp; + } + + // Use GetParent for display purposes, but if you want to tell the parent to update itself + // then use m_parent. The ValueObjectDynamicValue's parent is not the correct parent for + // displaying, they are really siblings, so for display it needs to route through to its grandparent. + virtual ValueObject * + GetParent() + { + return m_parent; + } + + virtual const ValueObject * + GetParent() const + { + return m_parent; + } + + ValueObject * + GetNonBaseClassParent(); + + void + SetAddressTypeOfChildren(AddressType at) + { + m_address_type_of_ptr_or_ref_children = at; + } + + AddressType + GetAddressTypeOfChildren(); + + void + SetHasCompleteType() + { + m_did_calculate_complete_objc_class_type = true; + } + + //------------------------------------------------------------------ + /// Find out if a ValueObject might have children. + /// + /// This call is much more efficient than CalculateNumChildren() as + /// it doesn't need to complete the underlying type. This is designed + /// to be used in a UI environment in order to detect if the + /// disclosure triangle should be displayed or not. + /// + /// This function returns true for class, union, structure, + /// pointers, references, arrays and more. Again, it does so without + /// doing any expensive type completion. + /// + /// @return + /// Returns \b true if the ValueObject might have children, or \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + MightHaveChildren(); + +protected: + typedef ClusterManager<ValueObject> ValueObjectManager; + + class ChildrenManager + { + public: + ChildrenManager() : + m_mutex(Mutex::eMutexTypeRecursive), + m_children(), + m_children_count(0) + {} + + bool + HasChildAtIndex (size_t idx) + { + Mutex::Locker locker(m_mutex); + ChildrenIterator iter = m_children.find(idx); + ChildrenIterator end = m_children.end(); + return (iter != end); + } + + ValueObject* + GetChildAtIndex (size_t idx) + { + Mutex::Locker locker(m_mutex); + ChildrenIterator iter = m_children.find(idx); + ChildrenIterator end = m_children.end(); + if (iter == end) + return NULL; + else + return iter->second; + } + + void + SetChildAtIndex (size_t idx, ValueObject* valobj) + { + ChildrenPair pair(idx,valobj); // we do not need to be mutex-protected to make a pair + Mutex::Locker locker(m_mutex); + m_children.insert(pair); + } + + void + SetChildrenCount (size_t count) + { + m_children_count = count; + } + + size_t + GetChildrenCount () + { + return m_children_count; + } + + void + Clear() + { + m_children_count = 0; + Mutex::Locker locker(m_mutex); + m_children.clear(); + } + + private: + typedef std::map<size_t, ValueObject*> ChildrenMap; + typedef ChildrenMap::iterator ChildrenIterator; + typedef ChildrenMap::value_type ChildrenPair; + Mutex m_mutex; + ChildrenMap m_children; + size_t m_children_count; + }; + + //------------------------------------------------------------------ + // Classes that inherit from ValueObject can see and modify these + //------------------------------------------------------------------ + ValueObject * m_parent; // The parent value object, or NULL if this has no parent + ValueObject * m_root; // The root of the hierarchy for this ValueObject (or NULL if never calculated) + EvaluationPoint m_update_point; // Stores both the stop id and the full context at which this value was last + // updated. When we are asked to update the value object, we check whether + // the context & stop id are the same before updating. + ConstString m_name; // The name of this object + DataExtractor m_data; // A data extractor that can be used to extract the value. + Value m_value; + Error m_error; // An error object that can describe any errors that occur when updating values. + std::string m_value_str; // Cached value string that will get cleared if/when the value is updated. + std::string m_old_value_str;// Cached old value string from the last time the value was gotten + std::string m_location_str; // Cached location string that will get cleared if/when the value is updated. + std::string m_summary_str; // Cached summary string that will get cleared if/when the value is updated. + std::string m_object_desc_str; // Cached result of the "object printer". This differs from the summary + // in that the summary is consed up by us, the object_desc_string is builtin. + + ClangASTType m_override_type;// If the type of the value object should be overridden, the type to impose. + + ValueObjectManager *m_manager; // This object is managed by the root object (any ValueObject that gets created + // without a parent.) The manager gets passed through all the generations of + // dependent objects, and will keep the whole cluster of objects alive as long + // as a shared pointer to any of them has been handed out. Shared pointers to + // value objects must always be made with the GetSP method. + + ChildrenManager m_children; + std::map<ConstString, ValueObject *> m_synthetic_children; + + ValueObject* m_dynamic_value; + ValueObject* m_synthetic_value; + ValueObject* m_deref_valobj; + + lldb::ValueObjectSP m_addr_of_valobj_sp; // We have to hold onto a shared pointer to this one because it is created + // as an independent ValueObjectConstResult, which isn't managed by us. + + lldb::Format m_format; + lldb::Format m_last_format; + uint32_t m_last_format_mgr_revision; + lldb::TypeSummaryImplSP m_type_summary_sp; + lldb::TypeFormatImplSP m_type_format_sp; + lldb::SyntheticChildrenSP m_synthetic_children_sp; + ProcessModID m_user_id_of_forced_summary; + AddressType m_address_type_of_ptr_or_ref_children; + + bool m_value_is_valid:1, + m_value_did_change:1, + m_children_count_valid:1, + m_old_value_valid:1, + m_is_deref_of_parent:1, + m_is_array_item_for_pointer:1, + m_is_bitfield_for_scalar:1, + m_is_child_at_offset:1, + m_is_getting_summary:1, + m_did_calculate_complete_objc_class_type:1; + + friend class ClangExpressionDeclMap; // For GetValue + friend class ClangExpressionVariable; // For SetName + friend class Target; // For SetName + friend class ValueObjectConstResultImpl; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + + // Use the no-argument constructor to make a constant variable object (with no ExecutionContextScope.) + + ValueObject(); + + // Use this constructor to create a "root variable object". The ValueObject will be locked to this context + // through-out its lifespan. + + ValueObject (ExecutionContextScope *exe_scope, + AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad); + + // Use this constructor to create a ValueObject owned by another ValueObject. It will inherit the ExecutionContext + // of its parent. + + ValueObject (ValueObject &parent); + + ValueObjectManager * + GetManager() + { + return m_manager; + } + + virtual bool + UpdateValue () = 0; + + virtual void + CalculateDynamicValue (lldb::DynamicValueType use_dynamic); + + virtual lldb::DynamicValueType + GetDynamicValueTypeImpl () + { + return lldb::eNoDynamicValues; + } + + virtual bool + HasDynamicValueTypeInfo () + { + return false; + } + + virtual void + CalculateSyntheticValue (bool use_synthetic = true); + + // Should only be called by ValueObject::GetChildAtIndex() + // Returns a ValueObject managed by this ValueObject's manager. + virtual ValueObject * + CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + + // Should only be called by ValueObject::GetNumChildren() + virtual size_t + CalculateNumChildren() = 0; + + void + SetNumChildren (size_t num_children); + + void + SetValueDidChange (bool value_changed); + + void + SetValueIsValid (bool valid); + + void + ClearUserVisibleData(uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings); + + void + AddSyntheticChild (const ConstString &key, + ValueObject *valobj); + + DataExtractor & + GetDataExtractor (); + + void + ClearDynamicTypeInformation (); + + //------------------------------------------------------------------ + // Sublasses must implement the functions below. + //------------------------------------------------------------------ + + virtual ClangASTType + GetClangTypeImpl () = 0; + + const char * + GetLocationAsCStringImpl (const Value& value, + const DataExtractor& data); + +private: + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + + virtual ClangASTType + MaybeCalculateCompleteType (); + + lldb::ValueObjectSP + GetValueForExpressionPath_Impl(const char* expression_cstr, + const char** first_unparsed, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_value_type, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* final_task_on_target); + + // this method will ONLY expand [] expressions into a VOList and return + // the number of elements it added to the VOList + // it will NOT loop through expanding the follow-up of the expression_cstr + // for all objects in the list + int + ExpandArraySliceExpression(const char* expression_cstr, + const char** first_unparsed, + lldb::ValueObjectSP root, + lldb::ValueObjectListSP& list, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_value_type, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* final_task_on_target); + + + DISALLOW_COPY_AND_ASSIGN (ValueObject); + +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObject_h_ diff --git a/include/lldb/Core/ValueObjectCast.h b/include/lldb/Core/ValueObjectCast.h new file mode 100644 index 0000000..1538d7a --- /dev/null +++ b/include/lldb/Core/ValueObjectCast.h @@ -0,0 +1,87 @@ +//===-- ValueObjectDynamicValue.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_ValueObjectCast_h_ +#define liblldb_ValueObjectCast_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + +//--------------------------------------------------------------------------------- +// A ValueObject that represents a given value represented as a different type. +//--------------------------------------------------------------------------------- +class ValueObjectCast : public ValueObject +{ +public: + static lldb::ValueObjectSP + Create (ValueObject &parent, + const ConstString &name, + const ClangASTType &cast_type); + + virtual + ~ValueObjectCast(); + + virtual uint64_t + GetByteSize(); + + virtual size_t + CalculateNumChildren(); + + virtual lldb::ValueType + GetValueType() const; + + virtual bool + IsInScope (); + + virtual ValueObject * + GetParent() + { + if (m_parent) + return m_parent->GetParent(); + else + return NULL; + } + + virtual const ValueObject * + GetParent() const + { + if (m_parent) + return m_parent->GetParent(); + else + return NULL; + } + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + ClangASTType m_cast_type; + +private: + ValueObjectCast (ValueObject &parent, + const ConstString &name, + const ClangASTType &cast_type); + + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectCast); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectCast_h_ diff --git a/include/lldb/Core/ValueObjectChild.h b/include/lldb/Core/ValueObjectChild.h new file mode 100644 index 0000000..780529a --- /dev/null +++ b/include/lldb/Core/ValueObjectChild.h @@ -0,0 +1,122 @@ +//===-- ValueObjectChild.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_ValueObjectChild_h_ +#define liblldb_ValueObjectChild_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A child of another ValueObject. +//---------------------------------------------------------------------- +class ValueObjectChild : public ValueObject +{ +public: + virtual ~ValueObjectChild(); + + virtual uint64_t + GetByteSize() + { + return m_byte_size; + } + + virtual off_t + GetByteOffset() + { + return m_byte_offset; + } + + virtual uint32_t + GetBitfieldBitSize() + { + return m_bitfield_bit_size; + } + + virtual uint32_t + GetBitfieldBitOffset() + { + return m_bitfield_bit_offset; + } + + virtual lldb::ValueType + GetValueType() const; + + virtual size_t + CalculateNumChildren(); + + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + + virtual bool + IsInScope (); + + virtual bool + IsBaseClass () + { + return m_is_base_class; + } + + virtual bool + IsDereferenceOfParent () + { + return m_is_deref_of_parent; + } + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl () + { + return m_clang_type; + } + + ClangASTType m_clang_type; + ConstString m_type_name; + uint64_t m_byte_size; + int32_t m_byte_offset; + uint8_t m_bitfield_bit_size; + uint8_t m_bitfield_bit_offset; + bool m_is_base_class; + bool m_is_deref_of_parent; + +// +// void +// ReadValueFromMemory (ValueObject* parent, lldb::addr_t address); + +protected: + friend class ValueObject; + friend class ValueObjectConstResult; + ValueObjectChild (ValueObject &parent, + const ClangASTType &clang_type, + const ConstString &name, + uint64_t byte_size, + int32_t byte_offset, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool is_base_class, + bool is_deref_of_parent, + AddressType child_ptr_or_ref_addr_type); + + DISALLOW_COPY_AND_ASSIGN (ValueObjectChild); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectChild_h_ diff --git a/include/lldb/Core/ValueObjectConstResult.h b/include/lldb/Core/ValueObjectConstResult.h new file mode 100644 index 0000000..4964d05 --- /dev/null +++ b/include/lldb/Core/ValueObjectConstResult.h @@ -0,0 +1,179 @@ +//===-- ValueObjectConstResult.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_ValueObjectConstResult_h_ +#define liblldb_ValueObjectConstResult_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +#include "lldb/Core/ValueObjectConstResultImpl.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A frozen ValueObject copied into host memory +//---------------------------------------------------------------------- +class ValueObjectConstResult : public ValueObject +{ +public: + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size, + lldb::addr_t address = LLDB_INVALID_ADDRESS); + + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + const ClangASTType &clang_type, + const ConstString &name, + const DataExtractor &data, + lldb::addr_t address = LLDB_INVALID_ADDRESS); + + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + const ClangASTType &clang_type, + const ConstString &name, + const lldb::DataBufferSP &result_data_sp, + lldb::ByteOrder byte_order, + uint32_t addr_size, + lldb::addr_t address = LLDB_INVALID_ADDRESS); + + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + const ClangASTType &clang_type, + const ConstString &name, + lldb::addr_t address, + AddressType address_type, + uint32_t addr_byte_size); + + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name); + + // When an expression fails to evaluate, we return an error + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + const Error& error); + + virtual ~ValueObjectConstResult(); + + virtual uint64_t + GetByteSize(); + + virtual lldb::ValueType + GetValueType() const; + + virtual size_t + CalculateNumChildren(); + + virtual ConstString + GetTypeName(); + + virtual bool + IsInScope (); + + void + SetByteSize (size_t size); + + virtual lldb::ValueObjectSP + Dereference (Error &error); + + virtual ValueObject * + CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + + virtual lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + + virtual lldb::ValueObjectSP + AddressOf (Error &error); + + virtual lldb::addr_t + GetAddressOf (bool scalar_is_load_address = true, + AddressType *address_type = NULL); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + + virtual lldb::addr_t + GetLiveAddress() + { + return m_impl.GetLiveAddress(); + } + + virtual void + SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, + AddressType address_type = eAddressTypeLoad) + { + m_impl.SetLiveAddress(addr, + address_type); + } + + virtual lldb::ValueObjectSP + GetDynamicValue (lldb::DynamicValueType valueType); + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + ConstString m_type_name; + uint64_t m_byte_size; + + ValueObjectConstResultImpl m_impl; + +private: + friend class ValueObjectConstResultImpl; + ValueObjectConstResult (ExecutionContextScope *exe_scope, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size, + lldb::addr_t address); + + ValueObjectConstResult (ExecutionContextScope *exe_scope, + const ClangASTType &clang_type, + const ConstString &name, + const DataExtractor &data, + lldb::addr_t address); + + ValueObjectConstResult (ExecutionContextScope *exe_scope, + const ClangASTType &clang_type, + const ConstString &name, + const lldb::DataBufferSP &result_data_sp, + lldb::ByteOrder byte_order, + uint32_t addr_size, + lldb::addr_t address); + + ValueObjectConstResult (ExecutionContextScope *exe_scope, + const ClangASTType &clang_type, + const ConstString &name, + lldb::addr_t address, + AddressType address_type, + uint32_t addr_byte_size); + + ValueObjectConstResult (ExecutionContextScope *exe_scope, + const Value &value, + const ConstString &name); + + ValueObjectConstResult (ExecutionContextScope *exe_scope, + const Error& error); + + DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResult); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResult_h_ diff --git a/include/lldb/Core/ValueObjectConstResultChild.h b/include/lldb/Core/ValueObjectConstResultChild.h new file mode 100644 index 0000000..9063276 --- /dev/null +++ b/include/lldb/Core/ValueObjectConstResultChild.h @@ -0,0 +1,77 @@ +//===-- ValueObjectConstResultChild.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_ValueObjectConstResultChild_h_ +#define liblldb_ValueObjectConstResultChild_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResultImpl.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A child of a ValueObjectConstResult. +//---------------------------------------------------------------------- +class ValueObjectConstResultChild : public ValueObjectChild +{ +public: + + ValueObjectConstResultChild (ValueObject &parent, + const ClangASTType &clang_type, + const ConstString &name, + uint32_t byte_size, + int32_t byte_offset, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool is_base_class, + bool is_deref_of_parent); + + virtual ~ValueObjectConstResultChild(); + + virtual lldb::ValueObjectSP + Dereference (Error &error); + + virtual ValueObject * + CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + + virtual ClangASTType + GetClangType () + { + return ValueObjectChild::GetClangType(); + } + + virtual lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create); + + virtual lldb::ValueObjectSP + AddressOf (Error &error); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + +protected: + ValueObjectConstResultImpl m_impl; + +private: + friend class ValueObject; + friend class ValueObjectConstResult; + friend class ValueObjectConstResultImpl; + + DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResultChild); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultChild_h_ diff --git a/include/lldb/Core/ValueObjectConstResultImpl.h b/include/lldb/Core/ValueObjectConstResultImpl.h new file mode 100644 index 0000000..271b938 --- /dev/null +++ b/include/lldb/Core/ValueObjectConstResultImpl.h @@ -0,0 +1,96 @@ +//===-- ValueObjectConstResultImpl.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_ValueObjectConstResultImpl_h_ +#define liblldb_ValueObjectConstResultImpl_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A class wrapping common implementation details for operations in +// ValueObjectConstResult ( & Child ) that may need to jump from the host +// memory space into the target's memory space +//---------------------------------------------------------------------- +class ValueObjectConstResultImpl +{ +public: + + ValueObjectConstResultImpl (ValueObject* valobj, + lldb::addr_t live_address = LLDB_INVALID_ADDRESS); + + virtual + ~ValueObjectConstResultImpl() + { + } + + lldb::ValueObjectSP + Dereference (Error &error); + + ValueObject * + CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + + lldb::ValueObjectSP + GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create); + + lldb::ValueObjectSP + AddressOf (Error &error); + + bool + NeedsDerefOnTarget() + { + m_impl_backend->UpdateValueIfNeeded(false); + return (m_impl_backend->GetValue().GetValueType() == Value::eValueTypeHostAddress); + } + + lldb::addr_t + GetLiveAddress() + { + return m_live_address; + } + + void + SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, + AddressType address_type = eAddressTypeLoad) + { + m_live_address = addr; + m_live_address_type = address_type; + } + + lldb::ValueObjectSP + DerefOnTarget(); + + virtual lldb::addr_t + GetAddressOf (bool scalar_is_load_address = true, + AddressType *address_type = NULL); + + virtual size_t + GetPointeeData (DataExtractor& data, + uint32_t item_idx = 0, + uint32_t item_count = 1); + +private: + + ValueObject *m_impl_backend; + lldb::addr_t m_live_address; + AddressType m_live_address_type; + lldb::ValueObjectSP m_load_addr_backend; + lldb::ValueObjectSP m_address_of_backend; + + DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResultImpl); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultImpl_h_ diff --git a/include/lldb/Core/ValueObjectDynamicValue.h b/include/lldb/Core/ValueObjectDynamicValue.h new file mode 100644 index 0000000..c0f6baa --- /dev/null +++ b/include/lldb/Core/ValueObjectDynamicValue.h @@ -0,0 +1,133 @@ +//===-- ValueObjectDynamicValue.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_ValueObjectDynamicValue_h_ +#define liblldb_ValueObjectDynamicValue_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/Type.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A ValueObject that represents memory at a given address, viewed as some +// set lldb type. +//---------------------------------------------------------------------- +class ValueObjectDynamicValue : public ValueObject +{ +public: + virtual + ~ValueObjectDynamicValue(); + + virtual uint64_t + GetByteSize(); + + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + + virtual size_t + CalculateNumChildren(); + + virtual lldb::ValueType + GetValueType() const; + + virtual bool + IsInScope (); + + virtual bool + IsDynamic () + { + return true; + } + + virtual ValueObject * + GetParent() + { + if (m_parent) + return m_parent->GetParent(); + else + return NULL; + } + + virtual const ValueObject * + GetParent() const + { + if (m_parent) + return m_parent->GetParent(); + else + return NULL; + } + + virtual lldb::ValueObjectSP + GetStaticValue () + { + return m_parent->GetSP(); + } + + void + SetOwningSP (lldb::ValueObjectSP &owning_sp) + { + if (m_owning_valobj_sp == owning_sp) + return; + + assert (m_owning_valobj_sp.get() == NULL); + m_owning_valobj_sp = owning_sp; + } + + virtual bool + SetValueFromCString (const char *value_str, Error& error); + + virtual bool + SetData (DataExtractor &data, Error &error); + +protected: + virtual bool + UpdateValue (); + + virtual lldb::DynamicValueType + GetDynamicValueTypeImpl () + { + return m_use_dynamic; + } + + virtual bool + HasDynamicValueTypeInfo () + { + return true; + } + + virtual ClangASTType + GetClangTypeImpl (); + + Address m_address; ///< The variable that this value object is based upon + TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name + lldb::ValueObjectSP m_owning_valobj_sp; + lldb::DynamicValueType m_use_dynamic; + +private: + friend class ValueObject; + friend class ValueObjectConstResult; + ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic); + + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectDynamicValue); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectDynamicValue_h_ diff --git a/include/lldb/Core/ValueObjectList.h b/include/lldb/Core/ValueObjectList.h new file mode 100644 index 0000000..5bfe40b --- /dev/null +++ b/include/lldb/Core/ValueObjectList.h @@ -0,0 +1,90 @@ +//===-- ValueObjectList.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_ValueObjectList_h_ +#define liblldb_ValueObjectList_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/UserID.h" +#include "lldb/Target/ExecutionContextScope.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A collection of ValueObject values that +//---------------------------------------------------------------------- +class ValueObjectList +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ValueObjectList (); + + ValueObjectList (const ValueObjectList &rhs); + + ~ValueObjectList(); + + const ValueObjectList & + operator = (const ValueObjectList &rhs); + + void + Append (const lldb::ValueObjectSP &val_obj_sp); + + void + Append (const ValueObjectList &valobj_list); + + lldb::ValueObjectSP + FindValueObjectByPointer (ValueObject *valobj); + + size_t + GetSize () const; + + void + Resize (size_t size); + + lldb::ValueObjectSP + GetValueObjectAtIndex (size_t idx); + + lldb::ValueObjectSP + RemoveValueObjectAtIndex (size_t idx); + + void + SetValueObjectAtIndex (size_t idx, + const lldb::ValueObjectSP &valobj_sp); + + lldb::ValueObjectSP + FindValueObjectByValueName (const char *name); + + lldb::ValueObjectSP + FindValueObjectByUID (lldb::user_id_t uid); + + void + Swap (ValueObjectList &value_object_list); + +protected: + typedef std::vector<lldb::ValueObjectSP> collection; + //------------------------------------------------------------------ + // Classes that inherit from ValueObjectList can see and modify these + //------------------------------------------------------------------ + collection m_value_objects; + +}; + + +} // namespace lldb_private + +#endif // liblldb_ValueObjectList_h_ diff --git a/include/lldb/Core/ValueObjectMemory.h b/include/lldb/Core/ValueObjectMemory.h new file mode 100644 index 0000000..627d73e --- /dev/null +++ b/include/lldb/Core/ValueObjectMemory.h @@ -0,0 +1,91 @@ +//===-- ValueObjectMemory.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_ValueObjectMemory_h_ +#define liblldb_ValueObjectMemory_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/ClangASTType.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A ValueObject that represents memory at a given address, viewed as some +// set lldb type. +//---------------------------------------------------------------------- +class ValueObjectMemory : public ValueObject +{ +public: + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + const char *name, + const Address &address, + lldb::TypeSP &type_sp); + + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, + const char *name, + const Address &address, + const ClangASTType &ast_type); + + virtual + ~ValueObjectMemory(); + + virtual uint64_t + GetByteSize(); + + virtual ConstString + GetTypeName(); + + virtual size_t + CalculateNumChildren(); + + virtual lldb::ValueType + GetValueType() const; + + virtual bool + IsInScope (); + + virtual lldb::ModuleSP + GetModule(); + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + Address m_address; ///< The variable that this value object is based upon + lldb::TypeSP m_type_sp; + ClangASTType m_clang_type; + +private: + ValueObjectMemory (ExecutionContextScope *exe_scope, + const char *name, + const Address &address, + lldb::TypeSP &type_sp); + + ValueObjectMemory (ExecutionContextScope *exe_scope, + const char *name, + const Address &address, + const ClangASTType &ast_type); + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectMemory); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectMemory_h_ diff --git a/include/lldb/Core/ValueObjectRegister.h b/include/lldb/Core/ValueObjectRegister.h new file mode 100644 index 0000000..6820629 --- /dev/null +++ b/include/lldb/Core/ValueObjectRegister.h @@ -0,0 +1,195 @@ +//===-- ValueObjectRegister.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_ValueObjectRegister_h_ +#define liblldb_ValueObjectRegister_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A ValueObject that contains a root variable that may or may not +// have children. +//---------------------------------------------------------------------- +class ValueObjectRegisterContext : public ValueObject +{ +public: + + virtual + ~ValueObjectRegisterContext(); + + virtual uint64_t + GetByteSize(); + + virtual lldb::ValueType + GetValueType () const + { + return lldb::eValueTypeRegisterSet; + } + + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + + virtual size_t + CalculateNumChildren(); + + virtual ValueObject * + CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + lldb::RegisterContextSP m_reg_ctx_sp; + +private: + ValueObjectRegisterContext (ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp); + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectRegisterContext); +}; + +class ValueObjectRegisterSet : public ValueObject +{ +public: + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx); + + virtual + ~ValueObjectRegisterSet(); + + virtual uint64_t + GetByteSize(); + + virtual lldb::ValueType + GetValueType () const + { + return lldb::eValueTypeRegisterSet; + } + + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + + virtual size_t + CalculateNumChildren(); + + virtual ValueObject * + CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index); + + virtual lldb::ValueObjectSP + GetChildMemberWithName (const ConstString &name, bool can_create); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + lldb::RegisterContextSP m_reg_ctx_sp; + const RegisterSet *m_reg_set; + uint32_t m_reg_set_idx; + +private: + friend class ValueObjectRegisterContext; + ValueObjectRegisterSet (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx); + + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectRegisterSet); +}; + +class ValueObjectRegister : public ValueObject +{ +public: + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); + + virtual + ~ValueObjectRegister(); + + virtual uint64_t + GetByteSize(); + + virtual lldb::ValueType + GetValueType () const + { + return lldb::eValueTypeRegister; + } + + virtual ConstString + GetTypeName(); + + virtual size_t + CalculateNumChildren(); + + virtual bool + SetValueFromCString (const char *value_str, Error& error); + + virtual bool + SetData (DataExtractor &data, Error &error); + + virtual bool + ResolveValue (Scalar &scalar); + + virtual void + GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat = eGetExpressionPathFormatDereferencePointers); + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + lldb::RegisterContextSP m_reg_ctx_sp; + RegisterInfo m_reg_info; + RegisterValue m_reg_value; + ConstString m_type_name; + ClangASTType m_clang_type; + +private: + void + ConstructObject (uint32_t reg_num); + + friend class ValueObjectRegisterSet; + ValueObjectRegister (ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); + ValueObjectRegister (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); + + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectRegister); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectRegister_h_ diff --git a/include/lldb/Core/ValueObjectSyntheticFilter.h b/include/lldb/Core/ValueObjectSyntheticFilter.h new file mode 100644 index 0000000..f1d8c88 --- /dev/null +++ b/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -0,0 +1,182 @@ +//===-- ValueObjectSyntheticFilter.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_ValueObjectSyntheticFilter_h_ +#define liblldb_ValueObjectSyntheticFilter_h_ + +// C Includes +// C++ Includes +#include <map> +#include <vector> +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A ValueObject that obtains its children from some source other than +// real information +// This is currently used to implement Python-based children and filters +// but you can bind it to any source of synthetic information and have +// it behave accordingly +//---------------------------------------------------------------------- +class ValueObjectSynthetic : public ValueObject +{ +public: + virtual + ~ValueObjectSynthetic(); + + virtual uint64_t + GetByteSize(); + + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + + virtual bool + MightHaveChildren(); + + virtual size_t + CalculateNumChildren(); + + virtual lldb::ValueType + GetValueType() const; + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx, bool can_create); + + virtual lldb::ValueObjectSP + GetChildMemberWithName (const ConstString &name, bool can_create); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual lldb::ValueObjectSP + GetDynamicValue (lldb::DynamicValueType valueType); + + virtual bool + IsInScope (); + + virtual bool + HasSyntheticValue() + { + return false; + } + + virtual bool + IsSynthetic() { return true; } + + virtual void + CalculateSyntheticValue (bool use_synthetic) + { + } + + virtual bool + IsDynamic () + { + if (m_parent) + return m_parent->IsDynamic(); + else + return false; + } + + virtual lldb::ValueObjectSP + GetStaticValue () + { + if (m_parent) + return m_parent->GetStaticValue(); + else + return GetSP(); + } + + virtual lldb::DynamicValueType + GetDynamicValueType () + { + if (m_parent) + return m_parent->GetDynamicValueType(); + else + return lldb::eNoDynamicValues; + } + + virtual ValueObject * + GetParent() + { + if (m_parent) + return m_parent->GetParent(); + else + return NULL; + } + + virtual const ValueObject * + GetParent() const + { + if (m_parent) + return m_parent->GetParent(); + else + return NULL; + } + + virtual lldb::ValueObjectSP + GetNonSyntheticValue (); + + virtual bool + ResolveValue (Scalar &scalar) + { + if (m_parent) + return m_parent->ResolveValue(scalar); + return false; + } + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + virtual void + CreateSynthFilter (); + + // we need to hold on to the SyntheticChildren because someone might delete the type binding while we are alive + lldb::SyntheticChildrenSP m_synth_sp; + std::unique_ptr<SyntheticChildrenFrontEnd> m_synth_filter_ap; + + typedef std::map<uint32_t, ValueObject*> ByIndexMap; + typedef std::map<const char*, uint32_t> NameToIndexMap; + + typedef ByIndexMap::iterator ByIndexIterator; + typedef NameToIndexMap::iterator NameToIndexIterator; + + ByIndexMap m_children_byindex; + NameToIndexMap m_name_toindex; + uint32_t m_synthetic_children_count; // FIXME use the ValueObject's ChildrenManager instead of a special purpose solution + + ConstString m_parent_type_name; + + LazyBool m_might_have_children; + +private: + friend class ValueObject; + ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter); + + void + CopyParentData (); + + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectSynthetic); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectSyntheticFilter_h_ diff --git a/include/lldb/Core/ValueObjectVariable.h b/include/lldb/Core/ValueObjectVariable.h new file mode 100644 index 0000000..8a30b00 --- /dev/null +++ b/include/lldb/Core/ValueObjectVariable.h @@ -0,0 +1,90 @@ +//===-- ValueObjectVariable.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_ValueObjectVariable_h_ +#define liblldb_ValueObjectVariable_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A ValueObject that contains a root variable that may or may not +// have children. +//---------------------------------------------------------------------- +class ValueObjectVariable : public ValueObject +{ +public: + static lldb::ValueObjectSP + Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp); + + virtual + ~ValueObjectVariable(); + + virtual uint64_t + GetByteSize(); + + virtual ConstString + GetTypeName(); + + virtual ConstString + GetQualifiedTypeName(); + + virtual size_t + CalculateNumChildren(); + + virtual lldb::ValueType + GetValueType() const; + + virtual bool + IsInScope (); + + virtual lldb::ModuleSP + GetModule(); + + virtual SymbolContextScope * + GetSymbolContextScope(); + + virtual bool + GetDeclaration (Declaration &decl); + + virtual const char * + GetLocationAsCString (); + + virtual bool + SetValueFromCString (const char *value_str, Error& error); + + virtual bool + SetData (DataExtractor &data, Error &error); + +protected: + virtual bool + UpdateValue (); + + virtual ClangASTType + GetClangTypeImpl (); + + lldb::VariableSP m_variable_sp; ///< The variable that this value object is based upon + Value m_resolved_value; ///< The value that DWARFExpression resolves this variable to before we patch it up + +private: + ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp); + //------------------------------------------------------------------ + // For ValueObject only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (ValueObjectVariable); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectVariable_h_ diff --git a/include/lldb/Core/dwarf.h b/include/lldb/Core/dwarf.h new file mode 100644 index 0000000..bf77125 --- /dev/null +++ b/include/lldb/Core/dwarf.h @@ -0,0 +1,64 @@ +//===-- dwarf.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef DebugBase_dwarf_h_ +#define DebugBase_dwarf_h_ + +#include <stdint.h> +#include <stdbool.h> + +// Get the DWARF constant defintions from llvm +#include "llvm/Support/Dwarf.h" +// and stuff them in our default namespace +using namespace llvm::dwarf; + +typedef uint32_t dw_uleb128_t; +typedef int32_t dw_sleb128_t; +typedef uint16_t dw_attr_t; +typedef uint8_t dw_form_t; +typedef uint16_t dw_tag_t; +typedef uint64_t dw_addr_t; // Dwarf address define that must be big enough for any addresses in the compile units that get parsed + +#ifdef DWARFUTILS_DWARF64 +#define DWARF_REF_ADDR_SIZE 8 +typedef uint64_t dw_offset_t; // Dwarf Debug Information Entry offset for any offset into the file +#else +#define DWARF_REF_ADDR_SIZE 4 +typedef uint32_t dw_offset_t; // Dwarf Debug Information Entry offset for any offset into the file +#endif + +/* Constants */ +#define DW_INVALID_OFFSET (~(dw_offset_t)0) +#define DW_INVALID_INDEX 0xFFFFFFFFul + +// #define DW_ADDR_none 0x0 + +#define DW_EH_PE_MASK_ENCODING 0x0F + +//// The following are used only internally within lldb - don't +//// document them in the llvm Dwarf.h header file, we won't see +//// them in executable files anywhere. +//// These constants fit between DW_OP_lo_user (0xe0) and DW_OP_hi_user (0xff). +// +//#define DW_OP_APPLE_array_ref 0xEE // first pops index, then pops array; pushes array[index] +//#define DW_OP_APPLE_extern 0xEF // ULEB128 index of external object (i.e., an entity from the program that was used in the expression) +#define DW_OP_APPLE_uninit 0xF0 // This is actually generated by some apple compilers in locations lists +//#define DW_OP_APPLE_assign 0xF1 // pops value off and assigns it to second item on stack (2nd item must have assignable context) +//#define DW_OP_APPLE_address_of 0xF2 // gets the address of the top stack item (top item must be a variable, or have value_type that is an address already) +//#define DW_OP_APPLE_value_of 0xF3 // pops the value off the stack and pushes the value of that object (top item must be a variable, or expression local) +//#define DW_OP_APPLE_deref_type 0xF4 // gets the address of the top stack item (top item must be a variable, or a clang type) +//#define DW_OP_APPLE_expr_local 0xF5 // ULEB128 expression local index +//#define DW_OP_APPLE_constf 0xF6 // 1 byte float size, followed by constant float data +//#define DW_OP_APPLE_scalar_cast 0xF7 // Cast top of stack to 2nd in stack's type leaving all items in place +//#define DW_OP_APPLE_clang_cast 0xF8 // pointer size clang::Type * off the stack and cast top stack item to this type +//#define DW_OP_APPLE_clear 0xFE // clears the entire expression stack, ok if the stack is empty +//#define DW_OP_APPLE_error 0xFF // Stops expression evaluation and returns an error (no args) + + +#endif // DebugBase_dwarf_h_ diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h new file mode 100644 index 0000000..2f56c56 --- /dev/null +++ b/include/lldb/DataFormatters/CXXFormatterFunctions.h @@ -0,0 +1,874 @@ +//===-- CXXFormatterFunctions.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_CXXFormatterFunctions_h_ +#define liblldb_CXXFormatterFunctions_h_ + +#include <stdint.h> +#include <time.h> + +#include "lldb/lldb-forward.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/DataFormatters/FormatClasses.h" +#include "lldb/Target/Target.h" + +#include "clang/AST/ASTContext.h" + +namespace lldb_private { + namespace formatters + { + bool + ExtractValueFromObjCExpression (ValueObject &valobj, + const char* target_type, + const char* selector, + uint64_t &value); + + bool + ExtractSummaryFromObjCExpression (ValueObject &valobj, + const char* target_type, + const char* selector, + Stream &stream); + + lldb::ValueObjectSP + CallSelectorOnObject (ValueObject &valobj, + const char* return_type, + const char* selector, + uint64_t index); + + lldb::ValueObjectSP + CallSelectorOnObject (ValueObject &valobj, + const char* return_type, + const char* selector, + const char* key); + + size_t + ExtractIndexFromString (const char* item_name); + + time_t + GetOSXEpoch (); + + bool + Char16StringSummaryProvider (ValueObject& valobj, Stream& stream); // char16_t* and unichar* + + bool + Char32StringSummaryProvider (ValueObject& valobj, Stream& stream); // char32_t* + + bool + WCharStringSummaryProvider (ValueObject& valobj, Stream& stream); // wchar_t* + + bool + Char16SummaryProvider (ValueObject& valobj, Stream& stream); // char16_t and unichar + + bool + Char32SummaryProvider (ValueObject& valobj, Stream& stream); // char32_t + + bool + WCharSummaryProvider (ValueObject& valobj, Stream& stream); // wchar_t + + bool + LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream); // libc++ std::string + + bool + LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream); // libc++ std::wstring + + bool + ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream); + + SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + template<bool name_entries> + bool + NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSArraySummaryProvider (ValueObject& valobj, Stream& stream); + + template<bool cf_style> + bool + NSSetSummaryProvider (ValueObject& valobj, Stream& stream); + + template<bool needs_at> + bool + NSDataSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSNumberSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + CFBagSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSDateSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSBundleSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSStringSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + NSURLSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream); + + template <bool is_sel_ptr> + bool + ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream); + + bool + RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream); + + extern template bool + NSDictionarySummaryProvider<true> (ValueObject&, Stream&) ; + + extern template bool + NSDictionarySummaryProvider<false> (ValueObject&, Stream&) ; + + extern template bool + NSDataSummaryProvider<true> (ValueObject&, Stream&) ; + + extern template bool + NSDataSummaryProvider<false> (ValueObject&, Stream&) ; + + extern template bool + ObjCSELSummaryProvider<true> (ValueObject&, Stream&); + + extern template bool + ObjCSELSummaryProvider<false> (ValueObject&, Stream&); + + class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used; + uint32_t _priv1 : 2 ; + uint32_t _size : 30; + uint32_t _priv2 : 2; + uint32_t offset : 30; + uint32_t _priv3; + uint32_t _data; + }; + struct DataDescriptor_64 + { + uint64_t _used; + uint64_t _priv1 : 2 ; + uint64_t _size : 62; + uint64_t _priv2 : 2; + uint64_t offset : 62; + uint32_t _priv3; + uint64_t _data; + }; + public: + NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSArrayMSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + ClangASTType m_id_type; + std::vector<lldb::ValueObjectSP> m_children; + }; + + class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSArrayISyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + uint64_t m_items; + lldb::addr_t m_data_ptr; + ClangASTType m_id_type; + std::vector<lldb::ValueObjectSP> m_children; + }; + + class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSArrayCodeRunningSyntheticFrontEnd (); + }; + + SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _szidx : 6; + }; + + struct DictionaryItemDescriptor + { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + public: + NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryISyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + lldb::addr_t m_data_ptr; + ClangASTType m_pair_type; + std::vector<DictionaryItemDescriptor> m_children; + }; + + class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _kvo : 1; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + uint32_t _keys_addr; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _kvo : 1; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + uint64_t _keys_addr; + }; + struct DictionaryItemDescriptor + { + lldb::addr_t key_ptr; + lldb::addr_t val_ptr; + lldb::ValueObjectSP valobj_sp; + }; + public: + NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryMSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + lldb::ByteOrder m_order; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + ClangASTType m_pair_type; + std::vector<DictionaryItemDescriptor> m_children; + }; + + class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSDictionaryCodeRunningSyntheticFrontEnd (); + }; + + SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _szidx : 6; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint32_t _szidx : 6; + }; + + struct SetItemDescriptor + { + lldb::addr_t item_ptr; + lldb::ValueObjectSP valobj_sp; + }; + + public: + NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSSetISyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + lldb::addr_t m_data_ptr; + std::vector<SetItemDescriptor> m_children; + }; + + class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + + public: + NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSOrderedSetSyntheticFrontEnd (); + private: + uint32_t m_count; + std::map<uint32_t,lldb::ValueObjectSP> m_children; + }; + + class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + private: + struct DataDescriptor_32 + { + uint32_t _used : 26; + uint32_t _size; + uint32_t _mutations; + uint32_t _objs_addr; + }; + struct DataDescriptor_64 + { + uint64_t _used : 58; + uint64_t _size; + uint64_t _mutations; + uint64_t _objs_addr; + }; + struct SetItemDescriptor + { + lldb::addr_t item_ptr; + lldb::ValueObjectSP valobj_sp; + }; + public: + NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSSetMSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint8_t m_ptr_size; + DataDescriptor_32 *m_data_32; + DataDescriptor_64 *m_data_64; + std::vector<SetItemDescriptor> m_children; + }; + + class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~NSSetCodeRunningSyntheticFrontEnd (); + }; + + SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxVectorBoolSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint64_t m_count; + lldb::addr_t m_base_data_address; + EvaluateExpressionOptions m_options; + }; + + SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + bool + LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream); + + class LibstdcppVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibstdcppVectorBoolSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + uint64_t m_count; + lldb::addr_t m_base_data_address; + EvaluateExpressionOptions m_options; + }; + + SyntheticChildrenFrontEnd* LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibstdcppMapIteratorSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + lldb::addr_t m_pair_address; + ClangASTType m_pair_type; + EvaluateExpressionOptions m_options; + lldb::ValueObjectSP m_pair_sp; + }; + + SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibCxxMapIteratorSyntheticFrontEnd (); + private: + ValueObject *m_pair_ptr; + }; + + SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class VectorIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp, + ConstString item_name); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~VectorIteratorSyntheticFrontEnd (); + private: + ExecutionContextRef m_exe_ctx_ref; + ConstString m_item_name; + lldb::ValueObjectSP m_item_sp; + }; + + SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxSharedPtrSyntheticFrontEnd (); + private: + ValueObject* m_cntrl; + lldb::ValueObjectSP m_count_sp; + lldb::ValueObjectSP m_weak_count_sp; + uint8_t m_ptr_size; + lldb::ByteOrder m_byte_order; + }; + + SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxStdVectorSyntheticFrontEnd (); + private: + ValueObject* m_start; + ValueObject* m_finish; + ClangASTType m_element_type; + uint32_t m_element_size; + std::map<size_t,lldb::ValueObjectSP> m_children; + }; + + SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxStdListSyntheticFrontEnd (); + private: + bool + HasLoop(); + + size_t m_list_capping_size; + static const bool g_use_loop_detect = true; + lldb::addr_t m_node_address; + ValueObject* m_head; + ValueObject* m_tail; + ClangASTType m_element_type; + size_t m_count; + std::map<size_t,lldb::ValueObjectSP> m_children; + }; + + SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + virtual size_t + CalculateNumChildren (); + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update(); + + virtual bool + MightHaveChildren (); + + virtual size_t + GetIndexOfChildWithName (const ConstString &name); + + virtual + ~LibcxxStdMapSyntheticFrontEnd (); + private: + bool + GetDataType(); + + void + GetValueOffset (const lldb::ValueObjectSP& node); + + ValueObject* m_tree; + ValueObject* m_root_node; + ClangASTType m_element_type; + uint32_t m_skip_size; + size_t m_count; + std::map<size_t,lldb::ValueObjectSP> m_children; + }; + + SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_CXXFormatterFunctions_h_ diff --git a/include/lldb/DataFormatters/DataVisualization.h b/include/lldb/DataFormatters/DataVisualization.h new file mode 100644 index 0000000..499e0fe --- /dev/null +++ b/include/lldb/DataFormatters/DataVisualization.h @@ -0,0 +1,174 @@ +//===-- DataVisualization.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_DataVisualization_h_ +#define lldb_DataVisualization_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/DataFormatters/FormatClasses.h" +#include "lldb/DataFormatters/FormatManager.h" + +namespace lldb_private { + +// this class is the high-level front-end of LLDB Data Visualization +// code in FormatManager.h/cpp is the low-level implementation of this feature +// clients should refer to this class as the entry-point into the data formatters +// unless they have a good reason to bypass this and go to the backend +class DataVisualization +{ +public: + + // use this call to force the FM to consider itself updated even when there is no apparent reason for that + static void + ForceUpdate(); + + static uint32_t + GetCurrentRevision (); + + class ValueFormats + { + public: + static lldb::TypeFormatImplSP + GetFormat (ValueObject& valobj, lldb::DynamicValueType use_dynamic); + + static lldb::TypeFormatImplSP + GetFormat (const ConstString &type); + + static void + Add (const ConstString &type, const lldb::TypeFormatImplSP &entry); + + static bool + Delete (const ConstString &type); + + static void + Clear (); + + static void + LoopThrough (TypeFormatImpl::ValueCallback callback, void* callback_baton); + + static size_t + GetCount (); + + static lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForFormatAtIndex (size_t); + + static lldb::TypeFormatImplSP + GetFormatAtIndex (size_t); + }; + + static lldb::TypeSummaryImplSP + GetSummaryFormat(ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + + static lldb::TypeSummaryImplSP + GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp); + +#ifndef LLDB_DISABLE_PYTHON + static lldb::SyntheticChildrenSP + GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp); +#endif + + static lldb::TypeFilterImplSP + GetFilterForType (lldb::TypeNameSpecifierImplSP type_sp); + +#ifndef LLDB_DISABLE_PYTHON + static lldb::ScriptedSyntheticChildrenSP + GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp); +#endif + +#ifndef LLDB_DISABLE_PYTHON + static lldb::SyntheticChildrenSP + GetSyntheticChildren(ValueObject& valobj, + lldb::DynamicValueType use_dynamic); +#endif + + static bool + AnyMatches(ConstString type_name, + TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, + bool only_enabled = true, + const char** matching_category = NULL, + TypeCategoryImpl::FormatCategoryItems* matching_type = NULL); + + class NamedSummaryFormats + { + public: + static bool + GetSummaryFormat (const ConstString &type, lldb::TypeSummaryImplSP &entry); + + static void + Add (const ConstString &type, const lldb::TypeSummaryImplSP &entry); + + static bool + Delete (const ConstString &type); + + static void + Clear (); + + static void + LoopThrough (TypeSummaryImpl::SummaryCallback callback, void* callback_baton); + + static uint32_t + GetCount (); + }; + + class Categories + { + public: + + static bool + GetCategory (const ConstString &category, + lldb::TypeCategoryImplSP &entry, + bool allow_create = true); + + static void + Add (const ConstString &category); + + static bool + Delete (const ConstString &category); + + static void + Clear (); + + static void + Clear (const ConstString &category); + + static void + Enable (const ConstString& category, + TypeCategoryMap::Position = TypeCategoryMap::Default); + + static void + Disable (const ConstString& category); + + static void + Enable (const lldb::TypeCategoryImplSP& category, + TypeCategoryMap::Position = TypeCategoryMap::Default); + + static void + Disable (const lldb::TypeCategoryImplSP& category); + + static void + LoopThrough (FormatManager::CategoryCallback callback, void* callback_baton); + + static uint32_t + GetCount (); + + static lldb::TypeCategoryImplSP + GetCategoryAtIndex (size_t); + }; +}; + + +} // namespace lldb_private + +#endif // lldb_DataVisualization_h_ diff --git a/include/lldb/DataFormatters/FormatCache.h b/include/lldb/DataFormatters/FormatCache.h new file mode 100644 index 0000000..941b96c --- /dev/null +++ b/include/lldb/DataFormatters/FormatCache.h @@ -0,0 +1,101 @@ +//===-- FormatCache.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_FormatCache_h_ +#define lldb_FormatCache_h_ + +// C Includes +// C++ Includes +#include <map> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/DataFormatters/FormatClasses.h" + +namespace lldb_private { +class FormatCache +{ +private: + struct Entry + { + private: + bool m_summary_cached : 1; + bool m_synthetic_cached : 1; + + lldb::TypeSummaryImplSP m_summary_sp; + lldb::SyntheticChildrenSP m_synthetic_sp; + public: + Entry (); + Entry (lldb::TypeSummaryImplSP); + Entry (lldb::SyntheticChildrenSP); + Entry (lldb::TypeSummaryImplSP,lldb::SyntheticChildrenSP); + + bool + IsSummaryCached (); + + bool + IsSyntheticCached (); + + lldb::TypeSummaryImplSP + GetSummary (); + + lldb::SyntheticChildrenSP + GetSynthetic (); + + void + SetSummary (lldb::TypeSummaryImplSP); + + void + SetSynthetic (lldb::SyntheticChildrenSP); + }; + typedef std::map<ConstString,Entry> CacheMap; + CacheMap m_map; + Mutex m_mutex; + + uint64_t m_cache_hits; + uint64_t m_cache_misses; + + Entry& + GetEntry (const ConstString& type); + +public: + FormatCache (); + + bool + GetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp); + + bool + GetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& synthetic_sp); + + void + SetSummary (const ConstString& type,lldb::TypeSummaryImplSP& summary_sp); + + void + SetSynthetic (const ConstString& type,lldb::SyntheticChildrenSP& synthetic_sp); + + void + Clear (); + + uint64_t + GetCacheHits () + { + return m_cache_hits; + } + + uint64_t + GetCacheMisses () + { + return m_cache_misses; + } +}; +} // namespace lldb_private + +#endif // lldb_FormatCache_h_ diff --git a/include/lldb/DataFormatters/FormatClasses.h b/include/lldb/DataFormatters/FormatClasses.h new file mode 100644 index 0000000..48a8eda --- /dev/null +++ b/include/lldb/DataFormatters/FormatClasses.h @@ -0,0 +1,128 @@ +//===-- FormatClasses.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_FormatClasses_h_ +#define lldb_FormatClasses_h_ + +// C Includes +#include <stdint.h> +#include <unistd.h> + +// C++ Includes +#include <string> +#include <vector> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/Type.h" + +#include "lldb/DataFormatters/TypeFormat.h" +#include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" + +namespace lldb_private { + +class TypeNameSpecifierImpl +{ +public: + TypeNameSpecifierImpl() : + m_is_regex(false), + m_type() + { + } + + TypeNameSpecifierImpl (const char* name, bool is_regex) : + m_is_regex(is_regex), + m_type() + { + if (name) + m_type.m_type_name.assign(name); + } + + // if constructing with a given type, is_regex cannot be true since we are + // giving an exact type to match + TypeNameSpecifierImpl (lldb::TypeSP type) : + m_is_regex(false), + m_type() + { + if (type) + { + m_type.m_type_name.assign(type->GetName().GetCString()); + m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); + } + } + + TypeNameSpecifierImpl (ClangASTType type) : + m_is_regex(false), + m_type() + { + if (type.IsValid()) + { + m_type.m_type_name.assign(type.GetConstTypeName().GetCString()); + m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); + } + } + + const char* + GetName() + { + if (m_type.m_type_name.size()) + return m_type.m_type_name.c_str(); + return NULL; + } + + lldb::TypeSP + GetTypeSP () + { + if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid()) + return m_type.m_typeimpl_sp->GetTypeSP(); + return lldb::TypeSP(); + } + + ClangASTType + GetClangASTType () + { + if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid()) + return m_type.m_typeimpl_sp->GetClangASTType(); + return ClangASTType(); + } + + bool + IsRegex() + { + return m_is_regex; + } + +private: + bool m_is_regex; + // this works better than TypeAndOrName because the latter only wraps a TypeSP + // whereas TypeImplSP can also be backed by a ClangASTType which is more commonly + // used in LLDB. moreover, TypeImplSP is also what is currently backing SBType + struct TypeOrName + { + std::string m_type_name; + lldb::TypeImplSP m_typeimpl_sp; + }; + TypeOrName m_type; + + +private: + DISALLOW_COPY_AND_ASSIGN(TypeNameSpecifierImpl); +}; + +} // namespace lldb_private + +#endif // lldb_FormatClasses_h_ diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h new file mode 100644 index 0000000..162e251 --- /dev/null +++ b/include/lldb/DataFormatters/FormatManager.h @@ -0,0 +1,251 @@ +//===-- FormatManager.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_FormatManager_h_ +#define lldb_FormatManager_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/DataFormatters/FormatCache.h" +#include "lldb/DataFormatters/FormatNavigator.h" +#include "lldb/DataFormatters/TypeCategory.h" +#include "lldb/DataFormatters/TypeCategoryMap.h" + +namespace lldb_private { + +// this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization +// class DataVisualization is the high-level front-end of this feature +// clients should refer to that class as the entry-point into the data formatters +// unless they have a good reason to bypass it and prefer to use this file's objects directly + +class FormatManager : public IFormatChangeListener +{ + typedef FormatNavigator<ConstString, TypeFormatImpl> ValueNavigator; + typedef ValueNavigator::MapType ValueMap; + typedef FormatMap<ConstString, TypeSummaryImpl> NamedSummariesMap; + typedef TypeCategoryMap::MapType::iterator CategoryMapIterator; +public: + + typedef TypeCategoryMap::CallbackType CategoryCallback; + + FormatManager (); + + ValueNavigator& + GetValueNavigator () + { + return m_value_nav; + } + + NamedSummariesMap& + GetNamedSummaryNavigator () + { + return m_named_summaries_map; + } + + void + EnableCategory (const ConstString& category_name, + TypeCategoryMap::Position pos = TypeCategoryMap::Default) + { + m_categories_map.Enable(category_name, + pos); + } + + void + DisableCategory (const ConstString& category_name) + { + m_categories_map.Disable(category_name); + } + + void + EnableCategory (const lldb::TypeCategoryImplSP& category, + TypeCategoryMap::Position pos = TypeCategoryMap::Default) + { + m_categories_map.Enable(category, + pos); + } + + void + DisableCategory (const lldb::TypeCategoryImplSP& category) + { + m_categories_map.Disable(category); + } + + bool + DeleteCategory (const ConstString& category_name) + { + return m_categories_map.Delete(category_name); + } + + void + ClearCategories () + { + return m_categories_map.Clear(); + } + + uint32_t + GetCategoriesCount () + { + return m_categories_map.GetCount(); + } + + lldb::TypeCategoryImplSP + GetCategoryAtIndex (size_t index) + { + return m_categories_map.GetAtIndex(index); + } + + void + LoopThroughCategories (CategoryCallback callback, void* param) + { + m_categories_map.LoopThrough(callback, param); + } + + lldb::TypeCategoryImplSP + GetCategory (const char* category_name = NULL, + bool can_create = true) + { + if (!category_name) + return GetCategory(m_default_category_name); + return GetCategory(ConstString(category_name)); + } + + lldb::TypeCategoryImplSP + GetCategory (const ConstString& category_name, + bool can_create = true); + + lldb::TypeSummaryImplSP + GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp); + + lldb::TypeFilterImplSP + GetFilterForType (lldb::TypeNameSpecifierImplSP type_sp); + +#ifndef LLDB_DISABLE_PYTHON + lldb::ScriptedSyntheticChildrenSP + GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp); +#endif + +#ifndef LLDB_DISABLE_PYTHON + lldb::SyntheticChildrenSP + GetSyntheticChildrenForType (lldb::TypeNameSpecifierImplSP type_sp); +#endif + + lldb::TypeSummaryImplSP + GetSummaryFormat (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + +#ifndef LLDB_DISABLE_PYTHON + lldb::SyntheticChildrenSP + GetSyntheticChildren (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); +#endif + + bool + AnyMatches (ConstString type_name, + TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, + bool only_enabled = true, + const char** matching_category = NULL, + TypeCategoryImpl::FormatCategoryItems* matching_type = NULL) + { + return m_categories_map.AnyMatches(type_name, + items, + only_enabled, + matching_category, + matching_type); + } + + static bool + GetFormatFromCString (const char *format_cstr, + bool partial_match_ok, + lldb::Format &format); + + static char + GetFormatAsFormatChar (lldb::Format format); + + static const char * + GetFormatAsCString (lldb::Format format); + + // if the user tries to add formatters for, say, "struct Foo" + // those will not match any type because of the way we strip qualifiers from typenames + // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo + // and strips the unnecessary qualifier + static ConstString + GetValidTypeName (const ConstString& type); + + // when DataExtractor dumps a vectorOfT, it uses a predefined format for each item + // this method returns it, or eFormatInvalid if vector_format is not a vectorOf + static lldb::Format + GetSingleItemFormat (lldb::Format vector_format); + + void + Changed () + { + __sync_add_and_fetch(&m_last_revision, +1); + m_format_cache.Clear (); + } + + uint32_t + GetCurrentRevision () + { + return m_last_revision; + } + + ~FormatManager () + { + } + +private: + FormatCache m_format_cache; + ValueNavigator m_value_nav; + NamedSummariesMap m_named_summaries_map; + uint32_t m_last_revision; + TypeCategoryMap m_categories_map; + + ConstString m_default_category_name; + ConstString m_system_category_name; + ConstString m_gnu_cpp_category_name; + ConstString m_libcxx_category_name; + ConstString m_objc_category_name; + ConstString m_corefoundation_category_name; + ConstString m_coregraphics_category_name; + ConstString m_coreservices_category_name; + ConstString m_vectortypes_category_name; + ConstString m_appkit_category_name; + + TypeCategoryMap& + GetCategories () + { + return m_categories_map; + } + + // WARNING: these are temporary functions that setup formatters + // while a few of these actually should be globally available and setup by LLDB itself + // most would actually belong to the users' lldbinit file or to some other form of configurable + // storage + void + LoadLibStdcppFormatters (); + + void + LoadLibcxxFormatters (); + + void + LoadSystemFormatters (); + + void + LoadObjCFormatters (); +}; + +} // namespace lldb_private + +#endif // lldb_FormatManager_h_ diff --git a/include/lldb/DataFormatters/FormatNavigator.h b/include/lldb/DataFormatters/FormatNavigator.h new file mode 100644 index 0000000..a738cfd --- /dev/null +++ b/include/lldb/DataFormatters/FormatNavigator.h @@ -0,0 +1,690 @@ +//===-- FormatNavigator.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_FormatNavigator_h_ +#define lldb_FormatNavigator_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/Core/Log.h" +#include "lldb/Core/RegularExpression.h" +#include "lldb/Core/ValueObject.h" + +#include "lldb/DataFormatters/FormatClasses.h" + +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTType.h" + +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/TargetList.h" + +namespace lldb_private { + +// this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization +// class DataVisualization is the high-level front-end of this feature +// clients should refer to that class as the entry-point into the data formatters +// unless they have a good reason to bypass it and prefer to use this file's objects directly +class IFormatChangeListener +{ +public: + virtual void + Changed () = 0; + + virtual + ~IFormatChangeListener () {} + + virtual uint32_t + GetCurrentRevision () = 0; + +}; + +static inline bool +IsWhitespace (char c) +{ + return ( (c == ' ') || (c == '\t') || (c == '\v') || (c == '\f') ); +} + +static inline bool +HasPrefix (const char* str1, const char* str2) +{ + return ( ::strstr(str1, str2) == str1 ); +} + +// if the user tries to add formatters for, say, "struct Foo" +// those will not match any type because of the way we strip qualifiers from typenames +// this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo +// and strips the unnecessary qualifier +static inline ConstString +GetValidTypeName_Impl (const ConstString& type) +{ + int strip_len = 0; + + if (type == false) + return type; + + const char* type_cstr = type.AsCString(); + + if ( HasPrefix(type_cstr, "class ") ) + strip_len = 6; + else if ( HasPrefix(type_cstr, "enum ") ) + strip_len = 5; + else if ( HasPrefix(type_cstr, "struct ") ) + strip_len = 7; + else if ( HasPrefix(type_cstr, "union ") ) + strip_len = 6; + + if (strip_len == 0) + return type; + + type_cstr += strip_len; + while (IsWhitespace(*type_cstr) && ++type_cstr) + ; + + return ConstString(type_cstr); +} + +template<typename KeyType, typename ValueType> +class FormatNavigator; + +template<typename KeyType, typename ValueType> +class FormatMap +{ +public: + + typedef typename ValueType::SharedPointer ValueSP; + typedef std::map<KeyType, ValueSP> MapType; + typedef typename MapType::iterator MapIterator; + typedef bool(*CallbackType)(void*, KeyType, const ValueSP&); + + FormatMap(IFormatChangeListener* lst) : + m_map(), + m_map_mutex(Mutex::eMutexTypeRecursive), + listener(lst) + { + } + + void + Add(KeyType name, + const ValueSP& entry) + { + if (listener) + entry->GetRevision() = listener->GetCurrentRevision(); + else + entry->GetRevision() = 0; + + Mutex::Locker locker(m_map_mutex); + m_map[name] = entry; + if (listener) + listener->Changed(); + } + + bool + Delete (KeyType name) + { + Mutex::Locker locker(m_map_mutex); + MapIterator iter = m_map.find(name); + if (iter == m_map.end()) + return false; + m_map.erase(name); + if (listener) + listener->Changed(); + return true; + } + + void + Clear () + { + Mutex::Locker locker(m_map_mutex); + m_map.clear(); + if (listener) + listener->Changed(); + } + + bool + Get(KeyType name, + ValueSP& entry) + { + Mutex::Locker locker(m_map_mutex); + MapIterator iter = m_map.find(name); + if (iter == m_map.end()) + return false; + entry = iter->second; + return true; + } + + void + LoopThrough (CallbackType callback, void* param) + { + if (callback) + { + Mutex::Locker locker(m_map_mutex); + MapIterator pos, end = m_map.end(); + for (pos = m_map.begin(); pos != end; pos++) + { + KeyType type = pos->first; + if (!callback(param, type, pos->second)) + break; + } + } + } + + uint32_t + GetCount () + { + return m_map.size(); + } + + ValueSP + GetValueAtIndex (size_t index) + { + Mutex::Locker locker(m_map_mutex); + MapIterator iter = m_map.begin(); + MapIterator end = m_map.end(); + while (index > 0) + { + iter++; + index--; + if (end == iter) + return ValueSP(); + } + return iter->second; + } + + KeyType + GetKeyAtIndex (size_t index) + { + Mutex::Locker locker(m_map_mutex); + MapIterator iter = m_map.begin(); + MapIterator end = m_map.end(); + while (index > 0) + { + iter++; + index--; + if (end == iter) + return KeyType(); + } + return iter->first; + } + +protected: + MapType m_map; + Mutex m_map_mutex; + IFormatChangeListener* listener; + + MapType& + map () + { + return m_map; + } + + Mutex& + mutex () + { + return m_map_mutex; + } + + friend class FormatNavigator<KeyType, ValueType>; + friend class FormatManager; + +}; + +template<typename KeyType, typename ValueType> +class FormatNavigator +{ +protected: + typedef FormatMap<KeyType,ValueType> BackEndType; + +public: + typedef typename BackEndType::MapType MapType; + typedef typename MapType::iterator MapIterator; + typedef typename MapType::key_type MapKeyType; + typedef typename MapType::mapped_type MapValueType; + typedef typename BackEndType::CallbackType CallbackType; + typedef typename std::shared_ptr<FormatNavigator<KeyType, ValueType> > SharedPointer; + + friend class TypeCategoryImpl; + + FormatNavigator(std::string name, + IFormatChangeListener* lst) : + m_format_map(lst), + m_name(name), + m_id_cs(ConstString("id")) + { + } + + void + Add (const MapKeyType &type, const MapValueType& entry) + { + Add_Impl(type, entry, (KeyType*)NULL); + } + + bool + Delete (ConstString type) + { + return Delete_Impl(type, (KeyType*)NULL); + } + + bool + Get(ValueObject& valobj, + MapValueType& entry, + lldb::DynamicValueType use_dynamic, + uint32_t* why = NULL) + { + uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice; + ClangASTType ast_type(valobj.GetClangType()); + bool ret = Get(valobj, ast_type, entry, use_dynamic, value); + if (ret) + entry = MapValueType(entry); + else + entry = MapValueType(); + if (why) + *why = value; + return ret; + } + + bool + Get (ConstString type, MapValueType& entry) + { + return Get_Impl(type, entry, (KeyType*)NULL); + } + + bool + GetExact (ConstString type, MapValueType& entry) + { + return GetExact_Impl(type, entry, (KeyType*)NULL); + } + + MapValueType + GetAtIndex (size_t index) + { + return m_format_map.GetValueAtIndex(index); + } + + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierAtIndex (size_t index) + { + return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL); + } + + void + Clear () + { + m_format_map.Clear(); + } + + void + LoopThrough (CallbackType callback, void* param) + { + m_format_map.LoopThrough(callback,param); + } + + uint32_t + GetCount () + { + return m_format_map.GetCount(); + } + +protected: + + BackEndType m_format_map; + + std::string m_name; + + DISALLOW_COPY_AND_ASSIGN(FormatNavigator); + + ConstString m_id_cs; + + void + Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy) + { + m_format_map.Add(type,entry); + } + + void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy) + { + m_format_map.Add(GetValidTypeName_Impl(type), entry); + } + + bool + Delete_Impl (ConstString type, ConstString *dummy) + { + return m_format_map.Delete(type); + } + + bool + Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy) + { + Mutex& x_mutex = m_format_map.mutex(); + lldb_private::Mutex::Locker locker(x_mutex); + MapIterator pos, end = m_format_map.map().end(); + for (pos = m_format_map.map().begin(); pos != end; pos++) + { + lldb::RegularExpressionSP regex = pos->first; + if ( ::strcmp(type.AsCString(),regex->GetText()) == 0) + { + m_format_map.map().erase(pos); + if (m_format_map.listener) + m_format_map.listener->Changed(); + return true; + } + } + return false; + } + + bool + Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy) + { + return m_format_map.Get(type, entry); + } + + bool + GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy) + { + return Get_Impl(type,entry, (KeyType*)0); + } + + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy) + { + ConstString key = m_format_map.GetKeyAtIndex(index); + if (key) + return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(), + false)); + else + return lldb::TypeNameSpecifierImplSP(); + } + + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy) + { + lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index); + if (regex.get() == NULL) + return lldb::TypeNameSpecifierImplSP(); + return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(), + true)); + } + + bool + Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy) + { + const char* key_cstr = key.AsCString(); + if (!key_cstr) + return false; + Mutex& x_mutex = m_format_map.mutex(); + lldb_private::Mutex::Locker locker(x_mutex); + MapIterator pos, end = m_format_map.map().end(); + for (pos = m_format_map.map().begin(); pos != end; pos++) + { + lldb::RegularExpressionSP regex = pos->first; + if (regex->Execute(key_cstr)) + { + value = pos->second; + return true; + } + } + return false; + } + + bool + GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy) + { + Mutex& x_mutex = m_format_map.mutex(); + lldb_private::Mutex::Locker locker(x_mutex); + MapIterator pos, end = m_format_map.map().end(); + for (pos = m_format_map.map().begin(); pos != end; pos++) + { + lldb::RegularExpressionSP regex = pos->first; + if (strcmp(regex->GetText(),key.AsCString()) == 0) + { + value = pos->second; + return true; + } + } + return false; + } + + bool + Get_BitfieldMatch (ValueObject& valobj, + ConstString typeName, + MapValueType& entry, + uint32_t& reason) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + // for bitfields, append size to the typename so one can custom format them + StreamString sstring; + sstring.Printf("%s:%d",typeName.AsCString(),valobj.GetBitfieldBitSize()); + ConstString bitfieldname = ConstString(sstring.GetData()); + if (log) + log->Printf("[Get_BitfieldMatch] appended bitfield info, final result is %s", bitfieldname.GetCString()); + if (Get(bitfieldname, entry)) + { + if (log) + log->Printf("[Get_BitfieldMatch] bitfield direct match found, returning"); + return true; + } + else + { + reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField; + if (log) + log->Printf("[Get_BitfieldMatch] no bitfield direct match"); + return false; + } + } + + bool Get_ObjC (ValueObject& valobj, + MapValueType& entry) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + lldb::ProcessSP process_sp = valobj.GetProcessSP(); + ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime(); + if (runtime == NULL) + { + if (log) + log->Printf("[Get_ObjC] no valid ObjC runtime, skipping dynamic"); + return false; + } + ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj)); + if (!objc_class_sp) + { + if (log) + log->Printf("[Get_ObjC] invalid ISA, skipping dynamic"); + return false; + } + ConstString name (objc_class_sp->GetClassName()); + if (log) + log->Printf("[Get_ObjC] dynamic type inferred is %s - looking for direct dynamic match", name.GetCString()); + if (Get(name, entry)) + { + if (log) + log->Printf("[Get_ObjC] direct dynamic match found, returning"); + return true; + } + if (log) + log->Printf("[Get_ObjC] no dynamic match"); + return false; + } + + bool + Get_Impl (ValueObject& valobj, + ClangASTType clang_type, + MapValueType& entry, + lldb::DynamicValueType use_dynamic, + uint32_t& reason) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + + if (!clang_type.IsValid()) + { + if (log) + log->Printf("[Get_Impl] type is invalid, returning"); + return false; + } + + clang_type = clang_type.RemoveFastQualifiers(); + + ConstString typeName(clang_type.GetConstTypeName()); + + if (valobj.GetBitfieldBitSize() > 0) + { + if (Get_BitfieldMatch(valobj, typeName, entry, reason)) + return true; + } + + if (log) + log->Printf("[Get_Impl] trying to get %s for VO name %s of type %s", + m_name.c_str(), + valobj.GetName().AsCString(), + typeName.AsCString()); + + if (Get(typeName, entry)) + { + if (log) + log->Printf("[Get] direct match found, returning"); + return true; + } + if (log) + log->Printf("[Get_Impl] no direct match"); + + // strip pointers and references and see if that helps + if (clang_type.IsReferenceType()) + { + if (log) + log->Printf("[Get_Impl] stripping reference"); + if (Get_Impl(valobj, clang_type.GetNonReferenceType(), entry, use_dynamic, reason) && !entry->SkipsReferences()) + { + reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; + return true; + } + } + else if (clang_type.IsPointerType()) + { + if (log) + log->Printf("[Get_Impl] stripping pointer"); + if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers()) + { + reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; + return true; + } + } + + bool canBeObjCDynamic = valobj.GetClangType().IsPossibleDynamicType (NULL, + false, // no C++ + true); // yes ObjC + + if (canBeObjCDynamic) + { + if (use_dynamic != lldb::eNoDynamicValues) + { + if (log) + log->Printf("[Get_Impl] allowed to figure out dynamic ObjC type"); + if (Get_ObjC(valobj,entry)) + { + reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery; + return true; + } + } + if (log) + log->Printf("[Get_Impl] dynamic disabled or failed - stripping ObjC pointer"); + if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers()) + { + reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference; + return true; + } + } + + // try to strip typedef chains + if (clang_type.IsTypedefType()) + { + if (log) + log->Printf("[Get_Impl] stripping typedef"); + if ((Get_Impl(valobj, clang_type.GetTypedefedType(), entry, use_dynamic, reason)) && entry->Cascades()) + { + reason |= lldb_private::eFormatterChoiceCriterionNavigatedTypedefs; + return true; + } + } + + // out of luck here + return false; + } + + // we are separately passing in valobj and type because the valobj is fixed (and is used for ObjC discovery and bitfield size) + // but the type can change (e.g. stripping pointers, ...) + bool Get (ValueObject& valobj, + ClangASTType clang_type, + MapValueType& entry, + lldb::DynamicValueType use_dynamic, + uint32_t& reason) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); + + if (Get_Impl (valobj, clang_type, entry, use_dynamic, reason)) + return true; + + // try going to the unqualified type + do { + if (log) + log->Printf("[Get] trying the unqualified type"); + if (!clang_type.IsValid()) + break; + + ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType(); + if (!unqual_clang_ast_type.IsValid()) + { + if (log) + log->Printf("[Get] could not get the unqual_clang_ast_type"); + break; + } + if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType()) + { + if (log) + log->Printf("[Get] unqualified type is there and is not the same, let's try"); + if (Get_Impl (valobj, unqual_clang_ast_type,entry, use_dynamic, reason)) + return true; + } + else if (log) + log->Printf("[Get] unqualified type same as original type"); + } while(false); + + // if all else fails, go to static type + if (valobj.IsDynamic()) + { + if (log) + log->Printf("[Get] going to static value"); + lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); + if (static_value_sp) + { + if (log) + log->Printf("[Get] has a static value - actually use it"); + if (Get(*static_value_sp.get(), static_value_sp->GetClangType(), entry, use_dynamic, reason)) + { + reason |= lldb_private::eFormatterChoiceCriterionWentToStaticValue; + return true; + } + } + } + + return false; + } +}; + +} // namespace lldb_private + +#endif // lldb_FormatNavigator_h_ diff --git a/include/lldb/DataFormatters/TypeCategory.h b/include/lldb/DataFormatters/TypeCategory.h new file mode 100644 index 0000000..b76d84f4 --- /dev/null +++ b/include/lldb/DataFormatters/TypeCategory.h @@ -0,0 +1,230 @@ +//===-- TypeCategory.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_TypeCategory_h_ +#define lldb_TypeCategory_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/DataFormatters/FormatNavigator.h" + +namespace lldb_private { + class TypeCategoryImpl + { + private: + + typedef FormatNavigator<ConstString, TypeSummaryImpl> SummaryNavigator; + typedef FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl> RegexSummaryNavigator; + + typedef FormatNavigator<ConstString, TypeFilterImpl> FilterNavigator; + typedef FormatNavigator<lldb::RegularExpressionSP, TypeFilterImpl> RegexFilterNavigator; + +#ifndef LLDB_DISABLE_PYTHON + typedef FormatNavigator<ConstString, ScriptedSyntheticChildren> SynthNavigator; + typedef FormatNavigator<lldb::RegularExpressionSP, ScriptedSyntheticChildren> RegexSynthNavigator; +#endif // #ifndef LLDB_DISABLE_PYTHON + + typedef SummaryNavigator::MapType SummaryMap; + typedef RegexSummaryNavigator::MapType RegexSummaryMap; + typedef FilterNavigator::MapType FilterMap; + typedef RegexFilterNavigator::MapType RegexFilterMap; +#ifndef LLDB_DISABLE_PYTHON + typedef SynthNavigator::MapType SynthMap; + typedef RegexSynthNavigator::MapType RegexSynthMap; +#endif // #ifndef LLDB_DISABLE_PYTHON + + public: + + typedef uint16_t FormatCategoryItems; + static const uint16_t ALL_ITEM_TYPES = UINT16_MAX; + + typedef SummaryNavigator::SharedPointer SummaryNavigatorSP; + typedef RegexSummaryNavigator::SharedPointer RegexSummaryNavigatorSP; + typedef FilterNavigator::SharedPointer FilterNavigatorSP; + typedef RegexFilterNavigator::SharedPointer RegexFilterNavigatorSP; +#ifndef LLDB_DISABLE_PYTHON + typedef SynthNavigator::SharedPointer SynthNavigatorSP; + typedef RegexSynthNavigator::SharedPointer RegexSynthNavigatorSP; +#endif // #ifndef LLDB_DISABLE_PYTHON + + TypeCategoryImpl (IFormatChangeListener* clist, + ConstString name); + + SummaryNavigatorSP + GetSummaryNavigator () + { + return SummaryNavigatorSP(m_summary_nav); + } + + RegexSummaryNavigatorSP + GetRegexSummaryNavigator () + { + return RegexSummaryNavigatorSP(m_regex_summary_nav); + } + + FilterNavigatorSP + GetFilterNavigator () + { + return FilterNavigatorSP(m_filter_nav); + } + + RegexFilterNavigatorSP + GetRegexFilterNavigator () + { + return RegexFilterNavigatorSP(m_regex_filter_nav); + } + + SummaryNavigator::MapValueType + GetSummaryForType (lldb::TypeNameSpecifierImplSP type_sp); + + FilterNavigator::MapValueType + GetFilterForType (lldb::TypeNameSpecifierImplSP type_sp); + +#ifndef LLDB_DISABLE_PYTHON + SynthNavigator::MapValueType + GetSyntheticForType (lldb::TypeNameSpecifierImplSP type_sp); +#endif + + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForSummaryAtIndex (size_t index); + + SummaryNavigator::MapValueType + GetSummaryAtIndex (size_t index); + + FilterNavigator::MapValueType + GetFilterAtIndex (size_t index); + + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForFilterAtIndex (size_t index); + +#ifndef LLDB_DISABLE_PYTHON + SynthNavigatorSP + GetSyntheticNavigator () + { + return SynthNavigatorSP(m_synth_nav); + } + + RegexSynthNavigatorSP + GetRegexSyntheticNavigator () + { + return RegexSynthNavigatorSP(m_regex_synth_nav); + } + + SynthNavigator::MapValueType + GetSyntheticAtIndex (size_t index); + + lldb::TypeNameSpecifierImplSP + GetTypeNameSpecifierForSyntheticAtIndex (size_t index); + +#endif // #ifndef LLDB_DISABLE_PYTHON + + bool + IsEnabled () const + { + return m_enabled; + } + + uint32_t + GetEnabledPosition() + { + if (m_enabled == false) + return UINT32_MAX; + else + return m_enabled_position; + } + + bool + Get (ValueObject& valobj, + lldb::TypeSummaryImplSP& entry, + lldb::DynamicValueType use_dynamic, + uint32_t* reason = NULL); + + bool + Get (ValueObject& valobj, + lldb::SyntheticChildrenSP& entry, + lldb::DynamicValueType use_dynamic, + uint32_t* reason = NULL); + + void + Clear (FormatCategoryItems items = ALL_ITEM_TYPES); + + bool + Delete (ConstString name, + FormatCategoryItems items = ALL_ITEM_TYPES); + + uint32_t + GetCount (FormatCategoryItems items = ALL_ITEM_TYPES); + + const char* + GetName () + { + return m_name.GetCString(); + } + + bool + AnyMatches (ConstString type_name, + FormatCategoryItems items = ALL_ITEM_TYPES, + bool only_enabled = true, + const char** matching_category = NULL, + FormatCategoryItems* matching_type = NULL); + + typedef std::shared_ptr<TypeCategoryImpl> SharedPointer; + + private: + SummaryNavigator::SharedPointer m_summary_nav; + RegexSummaryNavigator::SharedPointer m_regex_summary_nav; + FilterNavigator::SharedPointer m_filter_nav; + RegexFilterNavigator::SharedPointer m_regex_filter_nav; +#ifndef LLDB_DISABLE_PYTHON + SynthNavigator::SharedPointer m_synth_nav; + RegexSynthNavigator::SharedPointer m_regex_synth_nav; +#endif // #ifndef LLDB_DISABLE_PYTHON + + bool m_enabled; + + IFormatChangeListener* m_change_listener; + + Mutex m_mutex; + + ConstString m_name; + + uint32_t m_enabled_position; + + void + Enable (bool value, uint32_t position); + + void + Disable () + { + Enable(false, UINT32_MAX); + } + + friend class TypeCategoryMap; + + friend class FormatNavigator<ConstString, TypeSummaryImpl>; + friend class FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl>; + + friend class FormatNavigator<ConstString, TypeFilterImpl>; + friend class FormatNavigator<lldb::RegularExpressionSP, TypeFilterImpl>; + +#ifndef LLDB_DISABLE_PYTHON + friend class FormatNavigator<ConstString, ScriptedSyntheticChildren>; + friend class FormatNavigator<lldb::RegularExpressionSP, ScriptedSyntheticChildren>; +#endif // #ifndef LLDB_DISABLE_PYTHON + }; + +} // namespace lldb_private + +#endif // lldb_TypeCategory_h_ diff --git a/include/lldb/DataFormatters/TypeCategoryMap.h b/include/lldb/DataFormatters/TypeCategoryMap.h new file mode 100644 index 0000000..c2465ad --- /dev/null +++ b/include/lldb/DataFormatters/TypeCategoryMap.h @@ -0,0 +1,148 @@ +//===-- TypeCategoryMap.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_TypeCategoryMap_h_ +#define lldb_TypeCategoryMap_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/DataFormatters/FormatNavigator.h" +#include "lldb/DataFormatters/TypeCategory.h" + +namespace lldb_private { + class TypeCategoryMap + { + private: + typedef ConstString KeyType; + typedef TypeCategoryImpl ValueType; + typedef ValueType::SharedPointer ValueSP; + typedef std::list<lldb::TypeCategoryImplSP> ActiveCategoriesList; + typedef ActiveCategoriesList::iterator ActiveCategoriesIterator; + + public: + typedef std::map<KeyType, ValueSP> MapType; + typedef MapType::iterator MapIterator; + typedef bool(*CallbackType)(void*, const ValueSP&); + typedef uint32_t Position; + + static const Position First = 0; + static const Position Default = 1; + static const Position Last = UINT32_MAX; + + TypeCategoryMap (IFormatChangeListener* lst); + + void + Add (KeyType name, + const ValueSP& entry); + + bool + Delete (KeyType name); + + bool + Enable (KeyType category_name, + Position pos = Default); + + bool + Disable (KeyType category_name); + + bool + Enable (ValueSP category, + Position pos = Default); + + bool + Disable (ValueSP category); + + void + Clear (); + + bool + Get (KeyType name, + ValueSP& entry); + + bool + Get (uint32_t pos, + ValueSP& entry); + + void + LoopThrough (CallbackType callback, void* param); + + lldb::TypeCategoryImplSP + GetAtIndex (uint32_t); + + bool + AnyMatches (ConstString type_name, + TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, + bool only_enabled = true, + const char** matching_category = NULL, + TypeCategoryImpl::FormatCategoryItems* matching_type = NULL); + + uint32_t + GetCount () + { + return m_map.size(); + } + + lldb::TypeSummaryImplSP + GetSummaryFormat (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); + +#ifndef LLDB_DISABLE_PYTHON + lldb::SyntheticChildrenSP + GetSyntheticChildren (ValueObject& valobj, + lldb::DynamicValueType use_dynamic); +#endif + + private: + + class delete_matching_categories + { + lldb::TypeCategoryImplSP ptr; + public: + delete_matching_categories(lldb::TypeCategoryImplSP p) : ptr(p) + {} + + bool operator()(const lldb::TypeCategoryImplSP& other) + { + return ptr.get() == other.get(); + } + }; + + Mutex m_map_mutex; + IFormatChangeListener* listener; + + MapType m_map; + ActiveCategoriesList m_active_categories; + + MapType& map () + { + return m_map; + } + + ActiveCategoriesList& active_list () + { + return m_active_categories; + } + + Mutex& mutex () + { + return m_map_mutex; + } + + friend class FormatNavigator<KeyType, ValueType>; + friend class FormatManager; + }; +} // namespace lldb_private + +#endif // lldb_TypeCategoryMap_h_ diff --git a/include/lldb/DataFormatters/TypeFormat.h b/include/lldb/DataFormatters/TypeFormat.h new file mode 100644 index 0000000..77135c4 --- /dev/null +++ b/include/lldb/DataFormatters/TypeFormat.h @@ -0,0 +1,220 @@ +//===-- TypeFormat.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_TypeFormat_h_ +#define lldb_TypeFormat_h_ + +// C Includes + +// C++ Includes +#include <string> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/Core/ValueObject.h" + +namespace lldb_private { + class TypeFormatImpl + { + public: + class Flags + { + public: + + Flags () : + m_flags (lldb::eTypeOptionCascade) + {} + + Flags (const Flags& other) : + m_flags (other.m_flags) + {} + + Flags (uint32_t value) : + m_flags (value) + {} + + Flags& + operator = (const Flags& rhs) + { + if (&rhs != this) + m_flags = rhs.m_flags; + + return *this; + } + + Flags& + operator = (const uint32_t& rhs) + { + m_flags = rhs; + return *this; + } + + Flags& + Clear() + { + m_flags = 0; + return *this; + } + + bool + GetCascades () const + { + return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; + } + + Flags& + SetCascades (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionCascade; + else + m_flags &= ~lldb::eTypeOptionCascade; + return *this; + } + + bool + GetSkipPointers () const + { + return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; + } + + Flags& + SetSkipPointers (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipPointers; + else + m_flags &= ~lldb::eTypeOptionSkipPointers; + return *this; + } + + bool + GetSkipReferences () const + { + return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; + } + + Flags& + SetSkipReferences (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipReferences; + else + m_flags &= ~lldb::eTypeOptionSkipReferences; + return *this; + } + + uint32_t + GetValue () + { + return m_flags; + } + + void + SetValue (uint32_t value) + { + m_flags = value; + } + + private: + uint32_t m_flags; + }; + + TypeFormatImpl (lldb::Format f = lldb::eFormatInvalid, + const Flags& flags = Flags()); + + typedef std::shared_ptr<TypeFormatImpl> SharedPointer; + typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeFormatImplSP&); + + ~TypeFormatImpl () + { + } + + bool + Cascades () const + { + return m_flags.GetCascades(); + } + bool + SkipsPointers () const + { + return m_flags.GetSkipPointers(); + } + bool + SkipsReferences () const + { + return m_flags.GetSkipReferences(); + } + + void + SetCascades (bool value) + { + m_flags.SetCascades(value); + } + + void + SetSkipsPointers (bool value) + { + m_flags.SetSkipPointers(value); + } + + void + SetSkipsReferences (bool value) + { + m_flags.SetSkipReferences(value); + } + + lldb::Format + GetFormat () const + { + return m_format; + } + + void + SetFormat (lldb::Format fmt) + { + m_format = fmt; + } + + uint32_t + GetOptions () + { + return m_flags.GetValue(); + } + + void + SetOptions (uint32_t value) + { + m_flags.SetValue(value); + } + + uint32_t& + GetRevision () + { + return m_my_revision; + } + + std::string + GetDescription(); + + protected: + Flags m_flags; + lldb::Format m_format; + uint32_t m_my_revision; + + private: + DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl); + }; +} // namespace lldb_private + +#endif // lldb_TypeFormat_h_ diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h new file mode 100644 index 0000000..2183384 --- /dev/null +++ b/include/lldb/DataFormatters/TypeSummary.h @@ -0,0 +1,547 @@ +//===-- TypeSummary.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_TypeSummary_h_ +#define lldb_TypeSummary_h_ + +// C Includes +#include <stdint.h> +#include <unistd.h> + +// C++ Includes +#include <string> +#include <vector> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" +#include "lldb/Symbol/Type.h" + +namespace lldb_private { + + class TypeSummaryImpl + { + public: + class Flags + { + public: + + Flags () : + m_flags (lldb::eTypeOptionCascade) + {} + + Flags (const Flags& other) : + m_flags (other.m_flags) + {} + + Flags (uint32_t value) : + m_flags (value) + {} + + Flags& + operator = (const Flags& rhs) + { + if (&rhs != this) + m_flags = rhs.m_flags; + + return *this; + } + + Flags& + operator = (const uint32_t& rhs) + { + m_flags = rhs; + return *this; + } + + Flags& + Clear() + { + m_flags = 0; + return *this; + } + + bool + GetCascades () const + { + return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; + } + + Flags& + SetCascades (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionCascade; + else + m_flags &= ~lldb::eTypeOptionCascade; + return *this; + } + + bool + GetSkipPointers () const + { + return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; + } + + Flags& + SetSkipPointers (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipPointers; + else + m_flags &= ~lldb::eTypeOptionSkipPointers; + return *this; + } + + bool + GetSkipReferences () const + { + return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; + } + + Flags& + SetSkipReferences (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipReferences; + else + m_flags &= ~lldb::eTypeOptionSkipReferences; + return *this; + } + + bool + GetDontShowChildren () const + { + return (m_flags & lldb::eTypeOptionHideChildren) == lldb::eTypeOptionHideChildren; + } + + Flags& + SetDontShowChildren (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionHideChildren; + else + m_flags &= ~lldb::eTypeOptionHideChildren; + return *this; + } + + bool + GetDontShowValue () const + { + return (m_flags & lldb::eTypeOptionHideValue) == lldb::eTypeOptionHideValue; + } + + Flags& + SetDontShowValue (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionHideValue; + else + m_flags &= ~lldb::eTypeOptionHideValue; + return *this; + } + + bool + GetShowMembersOneLiner () const + { + return (m_flags & lldb::eTypeOptionShowOneLiner) == lldb::eTypeOptionShowOneLiner; + } + + Flags& + SetShowMembersOneLiner (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionShowOneLiner; + else + m_flags &= ~lldb::eTypeOptionShowOneLiner; + return *this; + } + + bool + GetHideItemNames () const + { + return (m_flags & lldb::eTypeOptionHideNames) == lldb::eTypeOptionHideNames; + } + + Flags& + SetHideItemNames (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionHideNames; + else + m_flags &= ~lldb::eTypeOptionHideNames; + return *this; + } + + uint32_t + GetValue () + { + return m_flags; + } + + void + SetValue (uint32_t value) + { + m_flags = value; + } + + private: + uint32_t m_flags; + }; + + typedef enum Type + { + eTypeUnknown, + eTypeString, + eTypeScript, + eTypeCallback + } Type; + + TypeSummaryImpl (const TypeSummaryImpl::Flags& flags); + + bool + Cascades () const + { + return m_flags.GetCascades(); + } + bool + SkipsPointers () const + { + return m_flags.GetSkipPointers(); + } + bool + SkipsReferences () const + { + return m_flags.GetSkipReferences(); + } + + bool + DoesPrintChildren () const + { + return !m_flags.GetDontShowChildren(); + } + + bool + DoesPrintValue () const + { + return !m_flags.GetDontShowValue(); + } + + bool + IsOneliner () const + { + return m_flags.GetShowMembersOneLiner(); + } + + bool + HideNames () const + { + return m_flags.GetHideItemNames(); + } + + void + SetCascades (bool value) + { + m_flags.SetCascades(value); + } + + void + SetSkipsPointers (bool value) + { + m_flags.SetSkipPointers(value); + } + + void + SetSkipsReferences (bool value) + { + m_flags.SetSkipReferences(value); + } + + void + SetDoesPrintChildren (bool value) + { + m_flags.SetDontShowChildren(!value); + } + + void + SetDoesPrintValue (bool value) + { + m_flags.SetDontShowValue(!value); + } + + void + SetIsOneliner (bool value) + { + m_flags.SetShowMembersOneLiner(value); + } + + void + SetHideNames (bool value) + { + m_flags.SetHideItemNames(value); + } + + uint32_t + GetOptions () + { + return m_flags.GetValue(); + } + + void + SetOptions (uint32_t value) + { + m_flags.SetValue(value); + } + + virtual + ~TypeSummaryImpl () + { + } + + // we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for + // extended periods of time and we trust the ValueObject to stay around for as long as it is required + // for us to generate its summary + virtual bool + FormatObject (ValueObject *valobj, + std::string& dest) = 0; + + virtual std::string + GetDescription () = 0; + + virtual bool + IsScripted () = 0; + + virtual Type + GetType () = 0; + + uint32_t& + GetRevision () + { + return m_my_revision; + } + + typedef std::shared_ptr<TypeSummaryImpl> SharedPointer; + typedef bool(*SummaryCallback)(void*, ConstString, const lldb::TypeSummaryImplSP&); + typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const lldb::TypeSummaryImplSP&); + + protected: + uint32_t m_my_revision; + Flags m_flags; + + private: + DISALLOW_COPY_AND_ASSIGN(TypeSummaryImpl); + }; + + // simple string-based summaries, using ${var to show data + struct StringSummaryFormat : public TypeSummaryImpl + { + std::string m_format; + + StringSummaryFormat(const TypeSummaryImpl::Flags& flags, + const char* f); + + const char* + GetSummaryString () const + { + return m_format.c_str(); + } + + void + SetSummaryString (const char* data) + { + if (data) + m_format.assign(data); + else + m_format.clear(); + } + + virtual + ~StringSummaryFormat() + { + } + + virtual bool + FormatObject(ValueObject *valobj, + std::string& dest); + + virtual std::string + GetDescription(); + + virtual bool + IsScripted () + { + return false; + } + + + virtual Type + GetType () + { + return TypeSummaryImpl::eTypeString; + } + + private: + DISALLOW_COPY_AND_ASSIGN(StringSummaryFormat); + }; + + // summaries implemented via a C++ function + struct CXXFunctionSummaryFormat : public TypeSummaryImpl + { + + // we should convert these to SBValue and SBStream if we ever cross + // the boundary towards the external world + typedef bool (*Callback)(ValueObject& valobj, Stream& dest); + + Callback m_impl; + std::string m_description; + + CXXFunctionSummaryFormat (const TypeSummaryImpl::Flags& flags, + Callback impl, + const char* description); + + Callback + GetBackendFunction () const + { + return m_impl; + } + + const char* + GetTextualInfo () const + { + return m_description.c_str(); + } + + void + SetBackendFunction (Callback cb_func) + { + m_impl = cb_func; + } + + void + SetTextualInfo (const char* descr) + { + if (descr) + m_description.assign(descr); + else + m_description.clear(); + } + + virtual + ~CXXFunctionSummaryFormat () + { + } + + virtual bool + FormatObject (ValueObject *valobj, + std::string& dest); + + virtual std::string + GetDescription (); + + virtual bool + IsScripted () + { + return false; + } + + virtual Type + GetType () + { + return TypeSummaryImpl::eTypeCallback; + } + + typedef std::shared_ptr<CXXFunctionSummaryFormat> SharedPointer; + + private: + DISALLOW_COPY_AND_ASSIGN(CXXFunctionSummaryFormat); + }; + +#ifndef LLDB_DISABLE_PYTHON + + // Python-based summaries, running script code to show data + struct ScriptSummaryFormat : public TypeSummaryImpl + { + std::string m_function_name; + std::string m_python_script; + lldb::ScriptInterpreterObjectSP m_script_function_sp; + + ScriptSummaryFormat(const TypeSummaryImpl::Flags& flags, + const char *function_name, + const char* python_script = NULL); + + const char* + GetFunctionName () const + { + return m_function_name.c_str(); + } + + const char* + GetPythonScript () const + { + return m_python_script.c_str(); + } + + void + SetFunctionName (const char* function_name) + { + if (function_name) + m_function_name.assign(function_name); + else + m_function_name.clear(); + m_python_script.clear(); + } + + void + SetPythonScript (const char* script) + { + if (script) + m_python_script.assign(script); + else + m_python_script.clear(); + } + + virtual + ~ScriptSummaryFormat () + { + } + + virtual bool + FormatObject (ValueObject *valobj, + std::string& dest); + + virtual std::string + GetDescription (); + + virtual bool + IsScripted () + { + return true; + } + + virtual Type + GetType () + { + return TypeSummaryImpl::eTypeScript; + } + + typedef std::shared_ptr<ScriptSummaryFormat> SharedPointer; + + + private: + DISALLOW_COPY_AND_ASSIGN(ScriptSummaryFormat); + }; +#endif +} // namespace lldb_private + +#endif // lldb_TypeSummary_h_ diff --git a/include/lldb/DataFormatters/TypeSynthetic.h b/include/lldb/DataFormatters/TypeSynthetic.h new file mode 100644 index 0000000..a32f4b7 --- /dev/null +++ b/include/lldb/DataFormatters/TypeSynthetic.h @@ -0,0 +1,594 @@ +//===-- TypeSynthetic.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_TypeSynthetic_h_ +#define lldb_TypeSynthetic_h_ + +// C Includes +#include <stdint.h> +#include <unistd.h> + +// C++ Includes +#include <string> +#include <vector> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/lldb-enumerations.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/ScriptInterpreterPython.h" +#include "lldb/Symbol/Type.h" + +namespace lldb_private { + class SyntheticChildrenFrontEnd + { + protected: + ValueObject &m_backend; + public: + + SyntheticChildrenFrontEnd (ValueObject &backend) : + m_backend(backend) + {} + + virtual + ~SyntheticChildrenFrontEnd () + { + } + + virtual size_t + CalculateNumChildren () = 0; + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx) = 0; + + virtual size_t + GetIndexOfChildWithName (const ConstString &name) = 0; + + // this function is assumed to always succeed and it if fails, the front-end should know to deal + // with it in the correct way (most probably, by refusing to return any children) + // the return value of Update() should actually be interpreted as "ValueObjectSyntheticFilter cache is good/bad" + // if =true, ValueObjectSyntheticFilter is allowed to use the children it fetched previously and cached + // if =false, ValueObjectSyntheticFilter must throw away its cache, and query again for children + virtual bool + Update () = 0; + + // if this function returns false, then CalculateNumChildren() MUST return 0 since UI frontends + // might validly decide not to inquire for children given a false return value from this call + // if it returns true, then CalculateNumChildren() can return any number >= 0 (0 being valid) + // it should if at all possible be more efficient than CalculateNumChildren() + virtual bool + MightHaveChildren () = 0; + + typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; + typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer; + + private: + DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd); + }; + + class SyntheticChildren + { + public: + + class Flags + { + public: + + Flags () : + m_flags (lldb::eTypeOptionCascade) + {} + + Flags (const Flags& other) : + m_flags (other.m_flags) + {} + + Flags (uint32_t value) : + m_flags (value) + {} + + Flags& + operator = (const Flags& rhs) + { + if (&rhs != this) + m_flags = rhs.m_flags; + + return *this; + } + + Flags& + operator = (const uint32_t& rhs) + { + m_flags = rhs; + return *this; + } + + Flags& + Clear() + { + m_flags = 0; + return *this; + } + + bool + GetCascades () const + { + return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; + } + + Flags& + SetCascades (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionCascade; + else + m_flags &= ~lldb::eTypeOptionCascade; + return *this; + } + + bool + GetSkipPointers () const + { + return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; + } + + Flags& + SetSkipPointers (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipPointers; + else + m_flags &= ~lldb::eTypeOptionSkipPointers; + return *this; + } + + bool + GetSkipReferences () const + { + return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; + } + + Flags& + SetSkipReferences (bool value = true) + { + if (value) + m_flags |= lldb::eTypeOptionSkipReferences; + else + m_flags &= ~lldb::eTypeOptionSkipReferences; + return *this; + } + + uint32_t + GetValue () + { + return m_flags; + } + + void + SetValue (uint32_t value) + { + m_flags = value; + } + + private: + uint32_t m_flags; + }; + + SyntheticChildren (const Flags& flags) : + m_flags(flags) + { + } + + virtual + ~SyntheticChildren () + { + } + + bool + Cascades () const + { + return m_flags.GetCascades(); + } + bool + SkipsPointers () const + { + return m_flags.GetSkipPointers(); + } + bool + SkipsReferences () const + { + return m_flags.GetSkipReferences(); + } + + void + SetCascades (bool value) + { + m_flags.SetCascades(value); + } + + void + SetSkipsPointers (bool value) + { + m_flags.SetSkipPointers(value); + } + + void + SetSkipsReferences (bool value) + { + m_flags.SetSkipReferences(value); + } + + uint32_t + GetOptions () + { + return m_flags.GetValue(); + } + + void + SetOptions (uint32_t value) + { + m_flags.SetValue(value); + } + + virtual bool + IsScripted () = 0; + + virtual std::string + GetDescription () = 0; + + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd (ValueObject &backend) = 0; + + typedef std::shared_ptr<SyntheticChildren> SharedPointer; + typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&); + + uint32_t& + GetRevision () + { + return m_my_revision; + } + + protected: + uint32_t m_my_revision; + Flags m_flags; + + private: + DISALLOW_COPY_AND_ASSIGN(SyntheticChildren); + }; + + class TypeFilterImpl : public SyntheticChildren + { + std::vector<std::string> m_expression_paths; + public: + TypeFilterImpl(const SyntheticChildren::Flags& flags) : + SyntheticChildren(flags), + m_expression_paths() + { + } + + TypeFilterImpl(const SyntheticChildren::Flags& flags, + const std::initializer_list<const char*> items) : + SyntheticChildren(flags), + m_expression_paths() + { + for (auto path : items) + AddExpressionPath (path); + } + + void + AddExpressionPath (const char* path) + { + AddExpressionPath(std::string(path)); + } + + void + Clear() + { + m_expression_paths.clear(); + } + + size_t + GetCount() const + { + return m_expression_paths.size(); + } + + const char* + GetExpressionPathAtIndex(size_t i) const + { + return m_expression_paths[i].c_str(); + } + + bool + SetExpressionPathAtIndex (size_t i, const char* path) + { + return SetExpressionPathAtIndex(i, std::string(path)); + } + + void + AddExpressionPath (const std::string& path) + { + bool need_add_dot = true; + if (path[0] == '.' || + (path[0] == '-' && path[1] == '>') || + path[0] == '[') + need_add_dot = false; + // add a '.' symbol to help forgetful users + if(!need_add_dot) + m_expression_paths.push_back(path); + else + m_expression_paths.push_back(std::string(".") + path); + } + + bool + SetExpressionPathAtIndex (size_t i, const std::string& path) + { + if (i >= GetCount()) + return false; + bool need_add_dot = true; + if (path[0] == '.' || + (path[0] == '-' && path[1] == '>') || + path[0] == '[') + need_add_dot = false; + // add a '.' symbol to help forgetful users + if(!need_add_dot) + m_expression_paths[i] = path; + else + m_expression_paths[i] = std::string(".") + path; + return true; + } + + bool + IsScripted () + { + return false; + } + + std::string + GetDescription (); + + class FrontEnd : public SyntheticChildrenFrontEnd + { + private: + TypeFilterImpl* filter; + public: + + FrontEnd(TypeFilterImpl* flt, + ValueObject &backend) : + SyntheticChildrenFrontEnd(backend), + filter(flt) + {} + + virtual + ~FrontEnd () + { + } + + virtual size_t + CalculateNumChildren () + { + return filter->GetCount(); + } + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx) + { + if (idx >= filter->GetCount()) + return lldb::ValueObjectSP(); + return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true); + } + + virtual bool + Update() { return false; } + + virtual bool + MightHaveChildren () + { + return filter->GetCount() > 0; + } + + virtual size_t + GetIndexOfChildWithName (const ConstString &name) + { + const char* name_cstr = name.GetCString(); + for (size_t i = 0; i < filter->GetCount(); i++) + { + const char* expr_cstr = filter->GetExpressionPathAtIndex(i); + if (expr_cstr) + { + if (*expr_cstr == '.') + expr_cstr++; + else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') + expr_cstr += 2; + } + if (!::strcmp(name_cstr, expr_cstr)) + return i; + } + return UINT32_MAX; + } + + typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; + + private: + DISALLOW_COPY_AND_ASSIGN(FrontEnd); + }; + + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) + { + return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl); + }; + + class CXXSyntheticChildren : public SyntheticChildren + { + public: + typedef SyntheticChildrenFrontEnd* (*CreateFrontEndCallback) (CXXSyntheticChildren*, lldb::ValueObjectSP); + protected: + CreateFrontEndCallback m_create_callback; + std::string m_description; + public: + CXXSyntheticChildren (const SyntheticChildren::Flags& flags, + const char* description, + CreateFrontEndCallback callback) : + SyntheticChildren(flags), + m_create_callback(callback), + m_description(description ? description : "") + { + } + + bool + IsScripted () + { + return false; + } + + std::string + GetDescription (); + + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd (ValueObject &backend) + { + return SyntheticChildrenFrontEnd::AutoPointer(m_create_callback(this, backend.GetSP())); + } + + private: + DISALLOW_COPY_AND_ASSIGN(CXXSyntheticChildren); + }; + +#ifndef LLDB_DISABLE_PYTHON + + class ScriptedSyntheticChildren : public SyntheticChildren + { + std::string m_python_class; + std::string m_python_code; + public: + + ScriptedSyntheticChildren (const SyntheticChildren::Flags& flags, + const char* pclass, + const char* pcode = NULL) : + SyntheticChildren(flags), + m_python_class(), + m_python_code() + { + if (pclass) + m_python_class = pclass; + if (pcode) + m_python_code = pcode; + } + + const char* + GetPythonClassName () + { + return m_python_class.c_str(); + } + + const char* + GetPythonCode () + { + return m_python_code.c_str(); + } + + void + SetPythonClassName (const char* fname) + { + m_python_class.assign(fname); + m_python_code.clear(); + } + + void + SetPythonCode (const char* script) + { + m_python_code.assign(script); + } + + std::string + GetDescription (); + + bool + IsScripted () + { + return true; + } + + class FrontEnd : public SyntheticChildrenFrontEnd + { + private: + std::string m_python_class; + lldb::ScriptInterpreterObjectSP m_wrapper_sp; + ScriptInterpreter *m_interpreter; + public: + + FrontEnd (std::string pclass, + ValueObject &backend); + + virtual + ~FrontEnd (); + + virtual size_t + CalculateNumChildren () + { + if (!m_wrapper_sp || m_interpreter == NULL) + return 0; + return m_interpreter->CalculateNumChildren(m_wrapper_sp); + } + + virtual lldb::ValueObjectSP + GetChildAtIndex (size_t idx); + + virtual bool + Update () + { + if (!m_wrapper_sp || m_interpreter == NULL) + return false; + + return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); + } + + virtual bool + MightHaveChildren () + { + if (!m_wrapper_sp || m_interpreter == NULL) + return false; + + return m_interpreter->MightHaveChildrenSynthProviderInstance(m_wrapper_sp); + } + + virtual size_t + GetIndexOfChildWithName (const ConstString &name) + { + if (!m_wrapper_sp || m_interpreter == NULL) + return UINT32_MAX; + return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString()); + } + + typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer; + + private: + DISALLOW_COPY_AND_ASSIGN(FrontEnd); + }; + + virtual SyntheticChildrenFrontEnd::AutoPointer + GetFrontEnd(ValueObject &backend) + { + return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ScriptedSyntheticChildren); + }; +#endif +} // namespace lldb_private + +#endif // lldb_TypeSynthetic_h_ diff --git a/include/lldb/Expression/ASTDumper.h b/include/lldb/Expression/ASTDumper.h new file mode 100644 index 0000000..47f7ea4 --- /dev/null +++ b/include/lldb/Expression/ASTDumper.h @@ -0,0 +1,43 @@ +//===-- ASTDumper.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_ASTDumper_h_ +#define liblldb_ASTDumper_h_ + +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeVisitor.h" + +#include "lldb/Core/Stream.h" +#include "llvm/ADT/DenseSet.h" + +namespace lldb_private +{ + +class ASTDumper +{ +public: + ASTDumper (clang::Decl *decl); + ASTDumper (clang::DeclContext *decl_ctx); + ASTDumper (const clang::Type *type); + ASTDumper (clang::QualType type); + ASTDumper (lldb::clang_type_t type); + ASTDumper (const ClangASTType &clang_type); + + const char *GetCString(); + void ToSTDERR(); + void ToLog(Log *log, const char *prefix); + void ToStream(lldb::StreamSP &stream); +private: + std::string m_dump; +}; + +} // namespace lldb_private + +#endif diff --git a/include/lldb/Expression/ASTResultSynthesizer.h b/include/lldb/Expression/ASTResultSynthesizer.h new file mode 100644 index 0000000..79709de --- /dev/null +++ b/include/lldb/Expression/ASTResultSynthesizer.h @@ -0,0 +1,184 @@ +//===-- ASTResultSynthesizer.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_ASTResultSynthesizer_h_ +#define liblldb_ASTResultSynthesizer_h_ + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/TaggedASTType.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h" +/// @brief Adds a result variable declaration to the ASTs for an expression. +/// +/// Users expect the expression "i + 3" to return a result, even if a result +/// variable wasn't specifically declared. To fulfil this requirement, LLDB adds +/// a result variable to the expression, transforming it to +/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the +/// resulting variable is mapped to the right piece of memory. +/// ASTResultSynthesizer's job is to add the variable and its initialization to +/// the ASTs for the expression, and it does so by acting as a SemaConsumer for +/// Clang. +//---------------------------------------------------------------------- +class ASTResultSynthesizer : public clang::SemaConsumer +{ +public: + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] target + /// The target, which contains the persistent variable store and the + /// AST importer. + //---------------------------------------------------------------------- + ASTResultSynthesizer(clang::ASTConsumer *passthrough, + Target &target); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + ~ASTResultSynthesizer(); + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context); + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD, bool DefinitionRequired); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats(); + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S); + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema(); +private: + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing + /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on + /// anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void TransformTopLevelDecl(clang::Decl *D); + + //---------------------------------------------------------------------- + /// Process an Objective-C method and produce the result variable and + /// initialization + /// + /// @param[in] MethodDecl + /// The method to process. + //---------------------------------------------------------------------- + bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); + + //---------------------------------------------------------------------- + /// Process a function and produce the result variable and initialization + /// + /// @param[in] FunDecl + /// The function to process. + //---------------------------------------------------------------------- + bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); + + //---------------------------------------------------------------------- + /// Process a function body and produce the result variable and + /// initialization + /// + /// @param[in] Body + /// The body of the function. + /// + /// @param[in] DC + /// The DeclContext of the function, into which the result variable + /// is inserted. + //---------------------------------------------------------------------- + bool SynthesizeBodyResult(clang::CompoundStmt *Body, + clang::DeclContext *DC); + + //---------------------------------------------------------------------- + /// Given a DeclContext for a function or method, find all types + /// declared in the context and record any persistent types found. + /// + /// @param[in] FunDeclCtx + /// The context for the function to process. + //---------------------------------------------------------------------- + void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); + + //---------------------------------------------------------------------- + /// Given a TypeDecl, if it declares a type whose name starts with a + /// dollar sign, register it as a pointer type in the target's scratch + /// AST context. + /// + /// @param[in] Body + /// The body of the function. + //---------------------------------------------------------------------- + void MaybeRecordPersistentType(clang::TypeDecl *D); + + clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. + Target &m_target; ///< The target, which contains the persistent variable store and the + clang::Sema *m_sema; ///< The Sema to use. +}; + +} + +#endif diff --git a/include/lldb/Expression/ASTStructExtractor.h b/include/lldb/Expression/ASTStructExtractor.h new file mode 100644 index 0000000..a1518de --- /dev/null +++ b/include/lldb/Expression/ASTStructExtractor.h @@ -0,0 +1,156 @@ +//===-- ASTStructExtractor.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_ASTStructExtractor_h_ +#define liblldb_ASTStructExtractor_h_ + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/ClangFunction.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h" +/// @brief Extracts and describes the argument structure for a wrapped function. +/// +/// This pass integrates with ClangFunction, which calls functions with custom +/// sets of arguments. To avoid having to implement the full calling convention +/// for the target's architecture, ClangFunction writes a simple wrapper +/// function that takes a pointer to an argument structure that contains room +/// for the address of the function to be called, the values of all its +/// arguments, and room for the function's return value. +/// +/// The definition of this struct is itself in the body of the wrapper function, +/// so Clang does the structure layout itself. ASTStructExtractor reads through +/// the AST for the wrapper funtion and finds the struct. +//---------------------------------------------------------------------- +class ASTStructExtractor : public clang::SemaConsumer +{ +public: + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] struct_name + /// The name of the structure to extract from the wrapper function. + /// + /// @param[in] function + /// The caller object whose members should be populated with information + /// about the argument struct. ClangFunction friends ASTStructExtractor + /// for this purpose. + //---------------------------------------------------------------------- + ASTStructExtractor(clang::ASTConsumer *passthrough, + const char *struct_name, + ClangFunction &function); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + virtual ~ASTStructExtractor(); + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context); + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD, bool DefinitionRequired); + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats(); + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S); + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema(); +private: + //---------------------------------------------------------------------- + /// Hunt the given FunctionDecl for the argument struct and place + /// information about it into m_function + /// + /// @param[in] F + /// The FunctionDecl to hunt. + //---------------------------------------------------------------------- + void + ExtractFromFunctionDecl(clang::FunctionDecl* F); + + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named the same as the wrapper + /// function name, recursing as necessary through LinkageSpecDecls, and + /// calling ExtractFromFunctionDecl on anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void + ExtractFromTopLevelDecl(clang::Decl* D); + + clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. + clang::Sema *m_sema; ///< The Sema to use. + clang::Action *m_action; ///< The Sema to use, cast to an Action so it's usable. + + ClangFunction &m_function; ///< The function to populate with information about the argument structure. + std::string m_struct_name; ///< The name of the structure to extract. +}; + +} + +#endif diff --git a/include/lldb/Expression/ClangASTSource.h b/include/lldb/Expression/ClangASTSource.h new file mode 100644 index 0000000..3e41a9e --- /dev/null +++ b/include/lldb/Expression/ClangASTSource.h @@ -0,0 +1,530 @@ +//===-- ClangASTSource.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_ClangASTSource_h_ +#define liblldb_ClangASTSource_h_ + +#include <set> + +#include "clang/Basic/IdentifierTable.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/SmallSet.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Provider for named objects defined in the debug info for Clang +/// +/// As Clang parses an expression, it may encounter names that are not +/// defined inside the expression, including variables, functions, and +/// types. Clang knows the name it is looking for, but nothing else. +/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) +/// to Clang for these names, consulting the ClangExpressionDeclMap to do +/// the actual lookups. +//---------------------------------------------------------------------- +class ClangASTSource : + public ClangExternalASTSourceCommon, + public ClangASTImporter::MapCompleter +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] declMap + /// A reference to the LLDB object that handles entity lookup. + //------------------------------------------------------------------ + ClangASTSource (const lldb::TargetSP &target) : + m_import_in_progress (false), + m_lookups_enabled (false), + m_target (target), + m_ast_context (NULL), + m_active_lookups () + { + m_ast_importer = m_target->GetClangASTImporter(); + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangASTSource(); + + //------------------------------------------------------------------ + /// Interface stubs. + //------------------------------------------------------------------ + clang::Decl *GetExternalDecl (uint32_t) { return NULL; } + clang::Stmt *GetExternalDeclStmt (uint64_t) { return NULL; } + clang::Selector GetExternalSelector (uint32_t) { return clang::Selector(); } + uint32_t GetNumExternalSelectors () { return 0; } + clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) + { return NULL; } + void MaterializeVisibleDecls (const clang::DeclContext *DC) + { return; } + + void InstallASTContext (clang::ASTContext *ast_context) + { + m_ast_context = ast_context; + m_ast_importer->InstallMapCompleter(ast_context, *this); + } + + // + // APIs for ExternalASTSource + // + + //------------------------------------------------------------------ + /// Look up all Decls that match a particular name. Only handles + /// Identifiers and DeclContexts that are either NamespaceDecls or + /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with + /// the result. + /// + /// The work for this function is done by + /// void FindExternalVisibleDecls (NameSearchContext &); + /// + /// @param[in] DC + /// The DeclContext to register the found Decls in. + /// + /// @param[in] Name + /// The name to find entries for. + /// + /// @return + /// Whatever SetExternalVisibleDeclsForName returns. + //------------------------------------------------------------------ + bool + FindExternalVisibleDeclsByName (const clang::DeclContext *DC, + clang::DeclarationName Name); + + //------------------------------------------------------------------ + /// Enumerate all Decls in a given lexical context. + /// + /// @param[in] DC + /// The DeclContext being searched. + /// + /// @param[in] isKindWeWant + /// If non-NULL, a callback function that returns true given the + /// DeclKinds of desired Decls, and false otherwise. + /// + /// @param[in] Decls + /// A vector that is filled in with matching Decls. + //------------------------------------------------------------------ + clang::ExternalLoadResult + FindExternalLexicalDecls (const clang::DeclContext *DC, + bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl<clang::Decl*> &Decls); + + //------------------------------------------------------------------ + /// Specify the layout of the contents of a RecordDecl. + /// + /// @param[in] Record + /// The record (in the parser's AST context) that needs to be + /// laid out. + /// + /// @param[out] Size + /// The total size of the record in bits. + /// + /// @param[out] Alignment + /// The alignment of the record in bits. + /// + /// @param[in] FieldOffsets + /// A map that must be populated with pairs of the record's + /// fields (in the parser's AST context) and their offsets + /// (measured in bits). + /// + /// @param[in] BaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ concrete base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @param[in] VirtualBaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ virtual base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @return + /// True <=> the layout is valid. + //----------------------------------------------------------------- + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets); + + //------------------------------------------------------------------ + /// Complete a TagDecl. + /// + /// @param[in] Tag + /// The Decl to be completed in place. + //------------------------------------------------------------------ + virtual void + CompleteType (clang::TagDecl *Tag); + + //------------------------------------------------------------------ + /// Complete an ObjCInterfaceDecl. + /// + /// @param[in] Class + /// The Decl to be completed in place. + //------------------------------------------------------------------ + virtual void + CompleteType (clang::ObjCInterfaceDecl *Class); + + //------------------------------------------------------------------ + /// Called on entering a translation unit. Tells Clang by calling + /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() + /// that this object has something to say about undefined names. + /// + /// @param[in] ASTConsumer + /// Unused. + //------------------------------------------------------------------ + void StartTranslationUnit (clang::ASTConsumer *Consumer); + + // + // APIs for NamespaceMapCompleter + // + + //------------------------------------------------------------------ + /// Look up the modules containing a given namespace and put the + /// appropriate entries in the namespace map. + /// + /// @param[in] namespace_map + /// The map to be completed. + /// + /// @param[in] name + /// The name of the namespace to be found. + /// + /// @param[in] parent_map + /// The map for the namespace's parent namespace, if there is + /// one. + //------------------------------------------------------------------ + void CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map, + const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const; + + // + // Helper APIs + // + + clang::NamespaceDecl * + AddNamespace (NameSearchContext &context, + ClangASTImporter::NamespaceMapSP &namespace_decls); + + //------------------------------------------------------------------ + /// The worker function for FindExternalVisibleDeclsByName. + /// + /// @param[in] context + /// The NameSearchContext to use when filing results. + //------------------------------------------------------------------ + virtual void FindExternalVisibleDecls (NameSearchContext &context); + + void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } + bool GetImportInProgress () { return m_import_in_progress; } + + void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } + bool GetLookupsEnabled () { return m_lookups_enabled; } + + //---------------------------------------------------------------------- + /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" + /// @brief Proxy for ClangASTSource + /// + /// Clang AST contexts like to own their AST sources, so this is a + /// state-free proxy object. + //---------------------------------------------------------------------- + class ClangASTSourceProxy : public ClangExternalASTSourceCommon + { + public: + ClangASTSourceProxy (ClangASTSource &original) : + m_original(original) + { + } + + bool + FindExternalVisibleDeclsByName (const clang::DeclContext *DC, + clang::DeclarationName Name) + { + return m_original.FindExternalVisibleDeclsByName(DC, Name); + } + + clang::ExternalLoadResult + FindExternalLexicalDecls (const clang::DeclContext *DC, + bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl<clang::Decl*> &Decls) + { + return m_original.FindExternalLexicalDecls(DC, isKindWeWant, Decls); + } + + void + CompleteType (clang::TagDecl *Tag) + { + return m_original.CompleteType(Tag); + } + + void + CompleteType (clang::ObjCInterfaceDecl *Class) + { + return m_original.CompleteType(Class); + } + + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) + { + return m_original.layoutRecordType(Record, + Size, + Alignment, + FieldOffsets, + BaseOffsets, + VirtualBaseOffsets); + } + + void StartTranslationUnit (clang::ASTConsumer *Consumer) + { + return m_original.StartTranslationUnit(Consumer); + } + + ClangASTMetadata * + GetMetadata(const void * object) + { + return m_original.GetMetadata(object); + } + + void + SetMetadata(const void * object, ClangASTMetadata &metadata) + { + return m_original.SetMetadata(object, metadata); + } + + bool + HasMetadata(const void * object) + { + return m_original.HasMetadata(object); + } + private: + ClangASTSource &m_original; + }; + + clang::ExternalASTSource *CreateProxy() + { + return new ClangASTSourceProxy(*this); + } + +protected: + //------------------------------------------------------------------ + /// Look for the complete version of an Objective-C interface, and + /// return it if found. + /// + /// @param[in] interface_decl + /// An ObjCInterfaceDecl that may not be the complete one. + /// + /// @return + /// NULL if the complete interface couldn't be found; + /// the complete interface otherwise. + //------------------------------------------------------------------ + clang::ObjCInterfaceDecl * + GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + ClangNamespaceDecl &namespace_decl, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Find all Objective-C methods matching a given selector. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the selector and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCMethodDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all Objective-C properties and ivars with a given name. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the name and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCPropertyAndIvarDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// A wrapper for ClangASTContext::CopyType that sets a flag that + /// indicates that we should not respond to queries during import. + /// + /// @param[in] dest_context + /// The target AST context, typically the parser's AST context. + /// + /// @param[in] source_context + /// The source AST context, typically the AST context of whatever + /// symbol file the type was found in. + /// + /// @param[in] clang_type + /// The source type. + /// + /// @return + /// The imported type. + //------------------------------------------------------------------ + ClangASTType + GuardedCopyType (const ClangASTType &src_type); + + friend struct NameSearchContext; + + bool m_import_in_progress; + bool m_lookups_enabled; + + const lldb::TargetSP m_target; ///< The target to use in finding variables and types. + clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + ClangASTImporter *m_ast_importer; ///< The target's AST importer. + std::set<const char *> m_active_lookups; +}; + +//---------------------------------------------------------------------- +/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Container for all objects relevant to a single name lookup +/// +/// LLDB needs to create Decls for entities it finds. This class communicates +/// what name is being searched for and provides helper functions to construct +/// Decls given appropriate type information. +//---------------------------------------------------------------------- +struct NameSearchContext { + ClangASTSource &m_ast_source; ///< The AST source making the request + llvm::SmallVectorImpl<clang::NamedDecl*> &m_decls; ///< The list of declarations already constructed + ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules + const clang::DeclarationName &m_decl_name; ///< The name being looked for + const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into + llvm::SmallSet <ClangASTType, 5> m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts + + struct { + bool variable : 1; + bool function_with_type_info : 1; + bool function : 1; + } m_found; + + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] astSource + /// A reference to the AST source making a request. + /// + /// @param[in] decls + /// A reference to a list into which new Decls will be placed. This + /// list is typically empty when the function is called. + /// + /// @param[in] name + /// The name being searched for (always an Identifier). + /// + /// @param[in] dc + /// The DeclContext to register Decls in. + //------------------------------------------------------------------ + NameSearchContext (ClangASTSource &astSource, + llvm::SmallVectorImpl<clang::NamedDecl*> &decls, + clang::DeclarationName &name, + const clang::DeclContext *dc) : + m_ast_source(astSource), + m_decls(decls), + m_decl_name(name), + m_decl_context(dc) + { + memset(&m_found, 0, sizeof(m_found)); + } + + //------------------------------------------------------------------ + /// Create a VarDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the VarDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddVarDecl(const ClangASTType &type); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the FunDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddFunDecl(const ClangASTType &type); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and generic + /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the + /// right places. + //------------------------------------------------------------------ + clang::NamedDecl *AddGenericFunDecl(); + + //------------------------------------------------------------------ + /// Create a TypeDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the TypeDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddTypeDecl(const ClangASTType &clang_type); + + + //------------------------------------------------------------------ + /// Add Decls from the provided DeclContextLookupResult to the list + /// of results. + /// + /// @param[in] result + /// The DeclContextLookupResult, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddLookupResult (clang::DeclContextLookupConstResult result); + + //------------------------------------------------------------------ + /// Add a NamedDecl to the list of results. + /// + /// @param[in] decl + /// The NamedDecl, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddNamedDecl (clang::NamedDecl *decl); +}; + +} + +#endif diff --git a/include/lldb/Expression/ClangExpression.h b/include/lldb/Expression/ClangExpression.h new file mode 100644 index 0000000..6e831e4 --- /dev/null +++ b/include/lldb/Expression/ClangExpression.h @@ -0,0 +1,153 @@ +//===-- ClangExpression.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_ClangExpression_h_ +#define liblldb_ClangExpression_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Target/Process.h" + +namespace lldb_private { + +class RecordingMemoryManager; + +//---------------------------------------------------------------------- +/// @class ClangExpression ClangExpression.h "lldb/Expression/ClangExpression.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangExpression encapsulates +/// the objects needed to parse and interpret or JIT an expression. It +/// uses the Clang parser to produce LLVM IR from the expression. +//---------------------------------------------------------------------- +class ClangExpression +{ +public: + enum ResultType { + eResultTypeAny, + eResultTypeId + }; + + ClangExpression () : + m_jit_process_wp(), + m_jit_start_addr (LLDB_INVALID_ADDRESS), + m_jit_end_addr (LLDB_INVALID_ADDRESS) + { + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~ClangExpression () + { + } + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + virtual const char * + Text () = 0; + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + virtual const char * + FunctionName () = 0; + + //------------------------------------------------------------------ + /// Return the language that should be used when parsing. To use + /// the default, return eLanguageTypeUnknown. + //------------------------------------------------------------------ + virtual lldb::LanguageType + Language () + { + return lldb::eLanguageTypeUnknown; + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + virtual ClangExpressionDeclMap * + DeclMap () = 0; + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + virtual clang::ASTConsumer * + ASTTransformer (clang::ASTConsumer *passthrough) = 0; + + //------------------------------------------------------------------ + /// Return the desired result type of the function, or + /// eResultTypeAny if indifferent. + //------------------------------------------------------------------ + virtual ResultType + DesiredResultType () + { + return eResultTypeAny; + } + + //------------------------------------------------------------------ + /// Flags + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + virtual bool + NeedsValidation () = 0; + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + virtual bool + NeedsVariableResolution () = 0; + + //------------------------------------------------------------------ + /// Return the address of the function's JIT-compiled code, or + /// LLDB_INVALID_ADDRESS if the function is not JIT compiled + //------------------------------------------------------------------ + lldb::addr_t + StartAddress () + { + return m_jit_start_addr; + } + +protected: + + lldb::ProcessWP m_jit_process_wp; + lldb::addr_t m_jit_start_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid. + lldb::addr_t m_jit_end_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid. + +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpression_h_ diff --git a/include/lldb/Expression/ClangExpressionDeclMap.h b/include/lldb/Expression/ClangExpressionDeclMap.h new file mode 100644 index 0000000..b2a43e0 --- /dev/null +++ b/include/lldb/Expression/ClangExpressionDeclMap.h @@ -0,0 +1,698 @@ +//===-- ClangExpressionDeclMap.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_ClangExpressionDeclMap_h_ +#define liblldb_ClangExpressionDeclMap_h_ + +// C Includes +#include <signal.h> +#include <stdint.h> + +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/ClangASTSource.h" +#include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" +/// @brief Manages named entities that are defined in LLDB's debug information. +/// +/// The Clang parser uses the ClangASTSource as an interface to request named +/// entities from outside an expression. The ClangASTSource reports back, listing +/// all possible objects corresponding to a particular name. But it in turn +/// relies on ClangExpressionDeclMap, which performs several important functions. +/// +/// First, it records what variables and functions were looked up and what Decls +/// were returned for them. +/// +/// Second, it constructs a struct on behalf of IRForTarget, recording which +/// variables should be placed where and relaying this information back so that +/// IRForTarget can generate context-independent code. +/// +/// Third, it "materializes" this struct on behalf of the expression command, +/// finding the current values of each variable and placing them into the +/// struct so that it can be passed to the JITted version of the IR. +/// +/// Fourth and finally, it "dematerializes" the struct after the JITted code has +/// has executed, placing the new values back where it found the old ones. +//---------------------------------------------------------------------- +class ClangExpressionDeclMap : + public ClangASTSource +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] keep_result_in_memory + /// If true, inhibits the normal deallocation of the memory for + /// the result persistent variable, and instead marks the variable + /// as persisting. + /// + /// @param[in] exe_ctx + /// The execution context to use when parsing. + //------------------------------------------------------------------ + ClangExpressionDeclMap (bool keep_result_in_memory, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionDeclMap (); + + //------------------------------------------------------------------ + /// Enable the state needed for parsing and IR transformation. + /// + /// @param[in] exe_ctx + /// The execution context to use when finding types for variables. + /// Also used to find a "scratch" AST context to store result types. + /// + /// @param[in] materializer + /// If non-NULL, the materializer to populate with information about + /// the variables to use + /// + /// @return + /// True if parsing is possible; false if it is unsafe to continue. + //------------------------------------------------------------------ + bool + WillParse (ExecutionContext &exe_ctx, + Materializer *materializer); + + //------------------------------------------------------------------ + /// [Used by ClangExpressionParser] For each variable that had an unknown + /// type at the beginning of parsing, determine its final type now. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + ResolveUnknownTypes(); + + //------------------------------------------------------------------ + /// Disable the state needed for parsing and IR transformation. + //------------------------------------------------------------------ + void + DidParse (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the list of persistent + /// variables for the process. + /// + /// @param[in] decl + /// The Clang declaration for the persistent variable, used for + /// lookup during parsing. + /// + /// @param[in] name + /// The name of the persistent variable, usually $something. + /// + /// @param[in] type + /// The type of the variable, in the Clang parser's context. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddPersistentVariable (const clang::NamedDecl *decl, + const ConstString &name, + TypeFromParser type, + bool is_result, + bool is_lvalue); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the struct that needs to + /// be materialized each time the expression runs. + /// + /// @param[in] decl + /// The Clang declaration for the variable. + /// + /// @param[in] name + /// The name of the variable. + /// + /// @param[in] value + /// The LLVM IR value for this variable. + /// + /// @param[in] size + /// The size of the variable in bytes. + /// + /// @param[in] alignment + /// The required alignment of the variable in bytes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddValueToStruct (const clang::NamedDecl *decl, + const ConstString &name, + llvm::Value *value, + size_t size, + off_t alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Finalize the struct, laying out the position + /// of each object in it. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + DoStructLayout (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get general information about the laid-out + /// struct after DoStructLayout() has been called. + /// + /// @param[out] num_elements + /// The number of elements in the struct. + /// + /// @param[out] size + /// The size of the struct, in bytes. + /// + /// @param[out] alignment + /// The alignment of the struct, in bytes. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructInfo (uint32_t &num_elements, + size_t &size, + off_t &alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get specific information about one field + /// of the laid-out struct after DoStructLayout() has been called. + /// + /// @param[out] decl + /// The parsed Decl for the field, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. In the case of the result + /// value, this will have the name $__lldb_result even if the + /// result value ends up having the name $1. This is an + /// implementation detail of IRForTarget. + /// + /// @param[out] value + /// The IR value for the field (usually a GlobalVariable). In + /// the case of the result value, this will have the correct + /// name ($1, for instance). This is an implementation detail + /// of IRForTarget. + /// + /// @param[out] offset + /// The offset of the field from the beginning of the struct. + /// As long as the struct is aligned according to its required + /// alignment, this offset will align the field correctly. + /// + /// @param[out] name + /// The name of the field as used in materialization. + /// + /// @param[in] index + /// The index of the field about which information is requested. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructElement (const clang::NamedDecl *&decl, + llvm::Value *&value, + off_t &offset, + ConstString &name, + uint32_t index); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get information about a function given its + /// Decl. + /// + /// @param[in] decl + /// The parsed Decl for the Function, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionInfo (const clang::NamedDecl *decl, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a function given nothing + /// but its name. Some functions are needed but didn't get Decls made + /// during parsing -- specifically, sel_registerName is never called + /// in the generated IR but we need to call it nonetheless. + /// + /// @param[in] name + /// The name of the function. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the address could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionAddress (const ConstString &name, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a symbol given nothing + /// but its name. + /// + /// @param[in] target + /// The target to find the symbol in. If not provided, + /// then the current parsing context's Target. + /// + /// @param[in] process + /// The process to use. For Objective-C symbols, the process's + /// Objective-C language runtime may be queried if the process + /// is non-NULL. + /// + /// @param[in] name + /// The name of the symbol. + /// + /// @return + /// Valid load address for the symbol + //------------------------------------------------------------------ + lldb::addr_t + GetSymbolAddress (Target &target, + Process *process, + const ConstString &name, + lldb::SymbolType symbol_type); + + lldb::addr_t + GetSymbolAddress (const ConstString &name, + lldb::SymbolType symbol_type); + + //------------------------------------------------------------------ + /// [Used by IRInterpreter] Get basic target information. + /// + /// @param[out] byte_order + /// The byte order of the target. + /// + /// @param[out] address_byte_size + /// The size of a pointer in bytes. + /// + /// @return + /// True if the information could be determined; false + /// otherwise. + //------------------------------------------------------------------ + struct TargetInfo + { + lldb::ByteOrder byte_order; + size_t address_byte_size; + + TargetInfo() : + byte_order(lldb::eByteOrderInvalid), + address_byte_size(0) + { + } + + bool IsValid() + { + return (byte_order != lldb::eByteOrderInvalid && + address_byte_size != 0); + } + }; + TargetInfo GetTargetInfo(); + + //------------------------------------------------------------------ + /// [Used by ClangASTSource] Find all entities matching a given name, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module/namespace, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] name + /// The name as a plain C string. The NameSearchContext contains + /// a DeclarationName for the name so at first the name may seem + /// redundant, but ClangExpressionDeclMap operates in RTTI land so + /// it can't access DeclarationName. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + ClangNamespaceDecl &namespace_decl, + unsigned int current_id); +private: + ClangExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. + ClangExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. + bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory. + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + ParserVars(ClangExpressionDeclMap &decl_map) : + m_exe_ctx(), + m_sym_ctx(), + m_persistent_vars(NULL), + m_enable_lookups(false), + m_materializer(NULL), + m_decl_map(decl_map) + { + } + + Target * + GetTarget() + { + if (m_exe_ctx.GetTargetPtr()) + return m_exe_ctx.GetTargetPtr(); + else if (m_sym_ctx.target_sp) + m_sym_ctx.target_sp.get(); + return NULL; + } + + ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. + SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. + ClangPersistentVariables *m_persistent_vars; ///< The persistent variables for the process. + bool m_enable_lookups; ///< Set to true during parsing if we have found the first "$__lldb" name. + TargetInfo m_target_info; ///< Basic information about the target. + Materializer *m_materializer; ///< If non-NULL, the materializer to use when reporting used variables. + private: + ClangExpressionDeclMap &m_decl_map; + DISALLOW_COPY_AND_ASSIGN (ParserVars); + }; + + std::unique_ptr<ParserVars> m_parser_vars; + + //---------------------------------------------------------------------- + /// Activate parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars() + { + if (!m_parser_vars.get()) + m_parser_vars.reset(new ParserVars(*this)); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars() + { + m_parser_vars.reset(); + } + + //---------------------------------------------------------------------- + /// The following values contain layout information for the materialized + /// struct, but are not specific to a single materialization + //---------------------------------------------------------------------- + struct StructVars { + StructVars() : + m_struct_alignment(0), + m_struct_size(0), + m_struct_laid_out(false), + m_result_name(), + m_object_pointer_type(NULL, NULL) + { + } + + off_t m_struct_alignment; ///< The alignment of the struct in bytes. + size_t m_struct_size; ///< The size of the struct in bytes. + bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). + ConstString m_result_name; ///< The name of the result variable ($1, for example) + TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists + }; + + std::unique_ptr<StructVars> m_struct_vars; + + //---------------------------------------------------------------------- + /// Activate struct variables + //---------------------------------------------------------------------- + void + EnableStructVars() + { + if (!m_struct_vars.get()) + m_struct_vars.reset(new struct StructVars); + } + + //---------------------------------------------------------------------- + /// Deallocate struct variables + //---------------------------------------------------------------------- + void + DisableStructVars() + { + m_struct_vars.reset(); + } + + //---------------------------------------------------------------------- + /// Get this parser's ID for use in extracting parser- and JIT-specific + /// data from persistent variables. + //---------------------------------------------------------------------- + uint64_t + GetParserID() + { + return (uint64_t)this; + } + + //------------------------------------------------------------------ + /// Given a target, find a data symbol that has the given name. + /// + /// @param[in] target + /// The target to use as the basis for the search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @return + /// The LLDB Symbol found, or NULL if none was found. + //--------------------------------------------------------- + const Symbol * + FindGlobalDataSymbol (Target &target, + const ConstString &name); + + //------------------------------------------------------------------ + /// Given a target, find a variable that matches the given name and + /// type. + /// + /// @param[in] target + /// The target to use as a basis for finding the variable. + /// + /// @param[in] module + /// If non-NULL, the module to search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] namespace_decl + /// If non-NULL and module is non-NULL, the parent namespace. + /// + /// @param[in] type + /// The required type for the variable. This function may be called + /// during parsing, in which case we don't know its type; hence the + /// default. + /// + /// @return + /// The LLDB Variable found, or NULL if none was found. + //------------------------------------------------------------------ + lldb::VariableSP + FindGlobalVariable (Target &target, + lldb::ModuleSP &module, + const ConstString &name, + ClangNamespaceDecl *namespace_decl, + TypeFromUser *type = NULL); + + //------------------------------------------------------------------ + /// Get the value of a variable in a given execution context and return + /// the associated Types if needed. + /// + /// @param[in] var + /// The variable to evaluate. + /// + /// @param[out] var_location + /// The variable location value to fill in + /// + /// @param[out] found_type + /// The type of the found value, as it was found in the user process. + /// This is only useful when the variable is being inspected on behalf + /// of the parser, hence the default. + /// + /// @param[out] parser_type + /// The type of the found value, as it was copied into the parser's + /// AST context. This is only useful when the variable is being + /// inspected on behalf of the parser, hence the default. + /// + /// @param[in] decl + /// The Decl to be looked up. + /// + /// @return + /// Return true if the value was successfully filled in. + //------------------------------------------------------------------ + bool + GetVariableValue (lldb::VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *found_type = NULL, + TypeFromParser *parser_type = NULL); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// Variable, and put it in the Tuple list. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + /// + /// @param[in] valobj + /// The LLDB ValueObject for that variable. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::VariableSP var, + lldb::ValueObjectSP valobj, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// persistent variable, and put it in the list of found entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] pvar + /// The persistent variable that needs a Decl. + /// + /// @param[in] current_id + /// The ID of the current invocation of FindExternalVisibleDecls + /// for logging purposes. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::ClangExpressionVariableSP &pvar_sp, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// symbol (treated as a variable), and put it in the list of found + /// entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + //------------------------------------------------------------------ + void + AddOneGenericVariable (NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// function. (Functions are not placed in the Tuple list.) Can + /// handle both fully typed functions and generic functions. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] fun + /// The Function that needs to be created. If non-NULL, this is + /// a fully-typed function. + /// + /// @param[in] sym + /// The Symbol that corresponds to a function that needs to be + /// created with generic type (unitptr_t foo(...)). + //------------------------------------------------------------------ + void + AddOneFunction (NameSearchContext &context, + Function *fun, + Symbol *sym, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// register. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] reg_info + /// The information corresponding to that register. + //------------------------------------------------------------------ + void + AddOneRegister (NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// type. (Types are not placed in the Tuple list.) + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + void + AddOneType (NameSearchContext &context, + TypeFromUser &type, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Copy a C++ class type into the parser's AST context and add a + /// member function declaration to it for the expression. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + + TypeFromParser + CopyClassType(TypeFromUser &type, + unsigned int current_id); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionDeclMap_h_ diff --git a/include/lldb/Expression/ClangExpressionParser.h b/include/lldb/Expression/ClangExpressionParser.h new file mode 100644 index 0000000..3247f20 --- /dev/null +++ b/include/lldb/Expression/ClangExpressionParser.h @@ -0,0 +1,151 @@ +//===-- ClangExpressionParser.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_ClangExpressionParser_h_ +#define liblldb_ClangExpressionParser_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Error.h" +#include "lldb/Expression/IRForTarget.h" + +#include <string> +#include <vector> + +namespace lldb_private +{ + +class IRExecutionUnit; + +//---------------------------------------------------------------------- +/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h" +/// @brief Encapsulates an instance of Clang that can parse expressions. +/// +/// ClangExpressionParser is responsible for preparing an instance of +/// ClangExpression for execution. ClangExpressionParser uses ClangExpression +/// as a glorified parameter list, performing the required parsing and +/// conversion to formats (DWARF bytecode, or JIT compiled machine code) +/// that can be executed. +//---------------------------------------------------------------------- +class ClangExpressionParser +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variabes. + /// + /// @param[in] exe_scope, + /// If non-NULL, an execution context scope that can help to + /// correctly create an expression with a valid process for + /// optional tuning Objective-C runtime support. Can be NULL. + /// + /// @param[in] expr + /// The expression to be parsed. + //------------------------------------------------------------------ + ClangExpressionParser (ExecutionContextScope *exe_scope, + ClangExpression &expr); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionParser (); + + //------------------------------------------------------------------ + /// Parse a single expression and convert it to IR using Clang. Don't + /// wrap the expression in anything at all. + /// + /// @param[in] stream + /// The stream to print errors to. + /// + /// @return + /// The number of errors encountered during parsing. 0 means + /// success. + //------------------------------------------------------------------ + unsigned + Parse (Stream &stream); + + //------------------------------------------------------------------ + /// Ready an already-parsed expression for execution, possibly + /// evaluating it statically. + /// + /// @param[out] func_addr + /// The address to which the function has been written. + /// + /// @param[out] func_end + /// The end of the function's allocated memory region. (func_addr + /// and func_end do not delimit an allocated region; the allocated + /// region may begin before func_addr.) + /// + /// @param[in] execution_unit_ap + /// After parsing, ownership of the execution unit for + /// for the expression is handed to this unique pointer. + /// + /// @param[in] exe_ctx + /// The execution context to write the function into. + /// + /// @param[out] evaluated_statically + /// Set to true if the expression could be interpreted statically; + /// untouched otherwise. + /// + /// @param[out] const_result + /// If the result of the expression is constant, and the + /// expression has no side effects, this is set to the result of the + /// expression. + /// + /// @param[in] execution_policy + /// Determines whether the expression must be JIT-compiled, must be + /// evaluated statically, or whether this decision may be made + /// opportunistically. + /// + /// @return + /// An error code indicating the success or failure of the operation. + /// Test with Success(). + //------------------------------------------------------------------ + Error + PrepareForExecution (lldb::addr_t &func_addr, + lldb::addr_t &func_end, + std::unique_ptr<IRExecutionUnit> &execution_unit_ap, + ExecutionContext &exe_ctx, + bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy); + + //------------------------------------------------------------------ + /// Disassemble the machine code for a JITted function from the target + /// process's memory and print the result to a stream. + /// + /// @param[in] stream + /// The stream to print disassembly to. + /// + /// @param[in] exc_context + /// The execution context to get the machine code from. + /// + /// @return + /// The error generated. If .Success() is true, disassembly succeeded. + //------------------------------------------------------------------ + Error + DisassembleFunction (Stream &stream, + ExecutionContext &exe_ctx); + +private: + ClangExpression & m_expr; ///< The expression to be parsed + std::unique_ptr<llvm::LLVMContext> m_llvm_context; ///< The LLVM context to generate IR into + std::unique_ptr<clang::FileManager> m_file_manager; ///< The Clang file manager object used by the compiler + std::unique_ptr<clang::CompilerInstance> m_compiler; ///< The Clang compiler used to parse expressions into IR + std::unique_ptr<clang::Builtin::Context> m_builtin_context; ///< Context for Clang built-ins + std::unique_ptr<clang::SelectorTable> m_selector_table; ///< Selector table for Objective-C methods + std::unique_ptr<clang::ASTContext> m_ast_context; ///< The AST context used to hold types and names for the parser + std::unique_ptr<clang::CodeGenerator> m_code_generator; ///< The Clang object that generates IR + std::unique_ptr<IRExecutionUnit> m_execution_unit; ///< The container for the finished Module +}; + +} + +#endif // liblldb_ClangExpressionParser_h_ diff --git a/include/lldb/Expression/ClangExpressionVariable.h b/include/lldb/Expression/ClangExpressionVariable.h new file mode 100644 index 0000000..620e604 --- /dev/null +++ b/include/lldb/Expression/ClangExpressionVariable.h @@ -0,0 +1,451 @@ +//===-- ClangExpressionVariable.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_ClangExpressionVariable_h_ +#define liblldb_ClangExpressionVariable_h_ + +// C Includes +#include <signal.h> +#include <stdint.h> +#include <string.h> + +// C++ Includes +#include <map> +#include <string> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Value.h" +#include "lldb/Symbol/TaggedASTType.h" + +namespace llvm { + class Value; +} + +namespace lldb_private { + +class ClangExpressionVariableList; +class ValueObjectConstResult; + +//---------------------------------------------------------------------- +/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" +/// @brief Encapsulates one variable for the expression parser. +/// +/// The expression parser uses variables in three different contexts: +/// +/// First, it stores persistent variables along with the process for use +/// in expressions. These persistent variables contain their own data +/// and are typed. +/// +/// Second, in an interpreted expression, it stores the local variables +/// for the expression along with the expression. These variables +/// contain their own data and are typed. +/// +/// Third, in a JIT-compiled expression, it stores the variables that +/// the expression needs to have materialized and dematerialized at each +/// execution. These do not contain their own data but are named and +/// typed. +/// +/// This class supports all of these use cases using simple type +/// polymorphism, and provides necessary support methods. Its interface +/// is RTTI-neutral. +//---------------------------------------------------------------------- +class ClangExpressionVariable +{ +public: + ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size); + + ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); + + //---------------------------------------------------------------------- + /// If the variable contains its own data, make a Value point at it. + /// If \a exe_ctx in not NULL, the value will be resolved in with + /// that execution context. + /// + /// @param[in] value + /// The value to point at the data. + /// + /// @param[in] exe_ctx + /// The execution context to use to resolve \a value. + /// + /// @return + /// True on success; false otherwise (in particular, if this variable + /// does not contain its own data). + //---------------------------------------------------------------------- + bool + PointValueAtData(Value &value, ExecutionContext *exe_ctx); + + lldb::ValueObjectSP + GetValueObject(); + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + + ParserVars() : + m_parser_type(), + m_named_decl (NULL), + m_llvm_value (NULL), + m_lldb_value (), + m_lldb_var (), + m_lldb_sym (NULL) + { + } + + TypeFromParser m_parser_type; ///< The type of the variable according to the parser + const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable + llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue + lldb_private::Value m_lldb_value; ///< The value found in LLDB for this variable + lldb::VariableSP m_lldb_var; ///< The original variable for this variable + const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol + }; + +private: + typedef std::map <uint64_t, ParserVars> ParserVarMap; + ParserVarMap m_parser_vars; + +public: + //---------------------------------------------------------------------- + /// Make this variable usable by the parser by allocating space for + /// parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars(uint64_t parser_id) + { + m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars(uint64_t parser_id) + { + m_parser_vars.erase(parser_id); + } + + //---------------------------------------------------------------------- + /// Access parser-specific variables + //---------------------------------------------------------------------- + ParserVars * + GetParserVars(uint64_t parser_id) + { + ParserVarMap::iterator i = m_parser_vars.find(parser_id); + + if (i == m_parser_vars.end()) + return NULL; + else + return &i->second; + } + + //---------------------------------------------------------------------- + /// The following values are valid if the variable is used by JIT code + //---------------------------------------------------------------------- + struct JITVars { + JITVars () : + m_alignment (0), + m_size (0), + m_offset (0) + { + } + + off_t m_alignment; ///< The required alignment of the variable, in bytes + size_t m_size; ///< The space required for the variable, in bytes + off_t m_offset; ///< The offset of the variable in the struct, in bytes + }; + +private: + typedef std::map <uint64_t, JITVars> JITVarMap; + JITVarMap m_jit_vars; + +public: + //---------------------------------------------------------------------- + /// Make this variable usable for materializing for the JIT by allocating + /// space for JIT-specific variables + //---------------------------------------------------------------------- + void + EnableJITVars(uint64_t parser_id) + { + m_jit_vars.insert(std::make_pair(parser_id, JITVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate JIT-specific variables + //---------------------------------------------------------------------- + void + DisableJITVars(uint64_t parser_id) + { + m_jit_vars.erase(parser_id); + } + + JITVars *GetJITVars(uint64_t parser_id) + { + JITVarMap::iterator i = m_jit_vars.find(parser_id); + + if (i == m_jit_vars.end()) + return NULL; + else + return &i->second; + } + + //---------------------------------------------------------------------- + /// Return the variable's size in bytes + //---------------------------------------------------------------------- + size_t + GetByteSize (); + + const ConstString & + GetName(); + + RegisterInfo * + GetRegisterInfo(); + + void + SetRegisterInfo (const RegisterInfo *reg_info); + + ClangASTType + GetClangType (); + + void + SetClangType (const ClangASTType &clang_type); + + TypeFromUser + GetTypeFromUser (); + + uint8_t * + GetValueBytes (); + + void + SetName (const ConstString &name); + + void + ValueUpdated (); + + // this function is used to copy the address-of m_live_sp into m_frozen_sp + // this is necessary because the results of certain cast and pointer-arithmetic + // operations (such as those described in bugzilla issues 11588 and 11618) generate + // frozen objcts that do not have a valid address-of, which can be troublesome when + // using synthetic children providers. transferring the address-of the live object + // solves these issues and provides the expected user-level behavior + void + TransferAddress (bool force = false); + + typedef std::shared_ptr<ValueObjectConstResult> ValueObjectConstResultSP; + + //---------------------------------------------------------------------- + /// Members + //---------------------------------------------------------------------- + enum Flags + { + EVNone = 0, + EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location specifically allocated for it by LLDB in the target process + EVIsProgramReference = 1 << 1, ///< This variable is a reference to a (possibly invalid) area managed by the target program + EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be allocated in the target process + EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results) + EVNeedsFreezeDry = 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization + EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it + EVTypeIsReference = 1 << 6, ///< The original type of this variable is a reference, so materialize the value rather than the location + EVUnknownType = 1 << 7, ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete + EVBareRegister = 1 << 8 ///< This variable is a direct reference to $pc or some other entity. + }; + + typedef uint16_t FlagType; + + FlagType m_flags; // takes elements of Flags + + lldb::ValueObjectSP m_frozen_sp; + lldb::ValueObjectSP m_live_sp; + + DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable); +}; + +//---------------------------------------------------------------------- +/// @class ClangExpressionVariableListBase ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" +/// @brief A list of variable references. +/// +/// This class stores variables internally, acting as the permanent store. +//---------------------------------------------------------------------- +class ClangExpressionVariableList +{ +public: + //---------------------------------------------------------------------- + /// Implementation of methods in ClangExpressionVariableListBase + //---------------------------------------------------------------------- + size_t + GetSize() + { + return m_variables.size(); + } + + lldb::ClangExpressionVariableSP + GetVariableAtIndex(size_t index) + { + lldb::ClangExpressionVariableSP var_sp; + if (index < m_variables.size()) + var_sp = m_variables[index]; + return var_sp; + } + + size_t + AddVariable (const lldb::ClangExpressionVariableSP &var_sp) + { + m_variables.push_back(var_sp); + return m_variables.size() - 1; + } + + bool + ContainsVariable (const lldb::ClangExpressionVariableSP &var_sp) + { + const size_t size = m_variables.size(); + for (size_t index = 0; index < size; ++index) + { + if (m_variables[index].get() == var_sp.get()) + return true; + } + return false; + } + + //---------------------------------------------------------------------- + /// Finds a variable by name in the list. + /// + /// @param[in] name + /// The name of the requested variable. + /// + /// @return + /// The variable requested, or NULL if that variable is not in the list. + //---------------------------------------------------------------------- + lldb::ClangExpressionVariableSP + GetVariable (const ConstString &name) + { + lldb::ClangExpressionVariableSP var_sp; + for (size_t index = 0, size = GetSize(); index < size; ++index) + { + var_sp = GetVariableAtIndex(index); + if (var_sp->GetName() == name) + return var_sp; + } + var_sp.reset(); + return var_sp; + } + + lldb::ClangExpressionVariableSP + GetVariable (const char *name) + { + lldb::ClangExpressionVariableSP var_sp; + if (name && name[0]) + { + for (size_t index = 0, size = GetSize(); index < size; ++index) + { + var_sp = GetVariableAtIndex(index); + const char *var_name_cstr = var_sp->GetName().GetCString(); + if (!var_name_cstr || !name) + continue; + if (::strcmp (var_name_cstr, name) == 0) + return var_sp; + } + var_sp.reset(); + } + return var_sp; + } + + //---------------------------------------------------------------------- + /// Finds a variable by NamedDecl in the list. + /// + /// @param[in] name + /// The name of the requested variable. + /// + /// @return + /// The variable requested, or NULL if that variable is not in the list. + //---------------------------------------------------------------------- + lldb::ClangExpressionVariableSP + GetVariable (const clang::NamedDecl *decl, uint64_t parser_id) + { + lldb::ClangExpressionVariableSP var_sp; + for (size_t index = 0, size = GetSize(); index < size; ++index) + { + var_sp = GetVariableAtIndex(index); + + ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(parser_id); + + if (parser_vars && parser_vars->m_named_decl == decl) + return var_sp; + } + var_sp.reset(); + return var_sp; + } + + //---------------------------------------------------------------------- + /// Create a new variable in the list and return its index + //---------------------------------------------------------------------- + lldb::ClangExpressionVariableSP + CreateVariable (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) + { + lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size)); + m_variables.push_back(var_sp); + return var_sp; + } + + lldb::ClangExpressionVariableSP + CreateVariable(const lldb::ValueObjectSP &valobj_sp) + { + lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(valobj_sp)); + m_variables.push_back(var_sp); + return var_sp; + } + + lldb::ClangExpressionVariableSP + CreateVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser& user_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) + { + lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size)); + var_sp->SetName (name); + var_sp->SetClangType (user_type); + m_variables.push_back(var_sp); + return var_sp; + } + + void + RemoveVariable (lldb::ClangExpressionVariableSP var_sp) + { + for (std::vector<lldb::ClangExpressionVariableSP>::iterator vi = m_variables.begin(), ve = m_variables.end(); + vi != ve; + ++vi) + { + if (vi->get() == var_sp.get()) + { + m_variables.erase(vi); + return; + } + } + } + + void + Clear() + { + m_variables.clear(); + } + +private: + std::vector <lldb::ClangExpressionVariableSP> m_variables; +}; + + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionVariable_h_ diff --git a/include/lldb/Expression/ClangFunction.h b/include/lldb/Expression/ClangFunction.h new file mode 100644 index 0000000..3f96f7b --- /dev/null +++ b/include/lldb/Expression/ClangFunction.h @@ -0,0 +1,652 @@ +//===-- ClangFunction.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_ClangFunction_h_ +#define lldb_ClangFunction_h_ + +// C Includes +// C++ Includes +#include <vector> +#include <list> +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/ClangExpression.h" +#include "lldb/Target/Process.h" + +namespace lldb_private +{ + +class ASTStructExtractor; +class ClangExpressionParser; + +//---------------------------------------------------------------------- +/// @class ClangFunction ClangFunction.h "lldb/Expression/ClangFunction.h" +/// @brief Encapsulates a function that can be called. +/// +/// A given ClangFunction object can handle a single function signature. +/// Once constructed, it can set up any number of concurrent calls to +/// functions with that signature. +/// +/// It performs the call by synthesizing a structure that contains the pointer +/// to the function and the arguments that should be passed to that function, +/// and producing a special-purpose JIT-compiled function that accepts a void* +/// pointing to this struct as its only argument and calls the function in the +/// struct with the written arguments. This method lets Clang handle the +/// vagaries of function calling conventions. +/// +/// The simplest use of the ClangFunction is to construct it with a +/// function representative of the signature you want to use, then call +/// ExecuteFunction(ExecutionContext &, Stream &, Value &). +/// +/// If you need to reuse the arguments for several calls, you can call +/// InsertFunction() followed by WriteFunctionArguments(), which will return +/// the location of the args struct for the wrapper function in args_addr_ref. +/// +/// If you need to call the function on the thread plan stack, you can also +/// call InsertFunction() followed by GetThreadPlanToCallFunction(). +/// +/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed +/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated +/// and its address returned in that variable. +/// +/// Any of the methods that take arg_addr_ptr can be passed NULL, and the +/// argument space will be managed for you. +//---------------------------------------------------------------------- +class ClangFunction : public ClangExpression +{ + friend class ASTStructExtractor; +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] function_ptr + /// The default function to be called. Can be overridden using + /// WriteFunctionArguments(). + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + ClangFunction (ExecutionContextScope &exe_scope, + Function &function_ptr, + ClangASTContext *ast_context, + const ValueList &arg_value_list); + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] return_qualtype + /// An opaque Clang QualType for the function result. Should be + /// defined in ast_context. + /// + /// @param[in] function_address + /// The address of the function to call. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + ClangFunction (ExecutionContextScope &exe_scope, + const ClangASTType &return_type, + const Address& function_address, + const ValueList &arg_value_list); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual + ~ClangFunction(); + + //------------------------------------------------------------------ + /// Compile the wrapper function + /// + /// @param[in] errors + /// The stream to print parser errors to. + /// + /// @return + /// The number of errors. + //------------------------------------------------------------------ + unsigned + CompileFunction (Stream &errors); + + //------------------------------------------------------------------ + /// Insert the default function wrapper and its default argument struct + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in,out] args_addr_ref + /// The address of the structure to write the arguments into. May + /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated + /// and args_addr_ref is pointed to it. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + InsertFunction (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + Stream &errors); + + //------------------------------------------------------------------ + /// Insert the default function wrapper (using the JIT) + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool WriteFunctionWrapper (ExecutionContext &exe_ctx, + Stream &errors); + + //------------------------------------------------------------------ + /// Insert the default function argument struct + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in,out] args_addr_ref + /// The address of the structure to write the arguments into. May + /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated + /// and args_addr_ref is pointed to it. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool WriteFunctionArguments (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + Stream &errors); + + //------------------------------------------------------------------ + /// Insert an argument struct with a non-default function address and + /// non-default argument values + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in,out] args_addr_ref + /// The address of the structure to write the arguments into. May + /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated + /// and args_addr_ref is pointed to it. + /// + /// @param[in] function_address + /// The address of the function to call. + /// + /// @param[in] arg_values + /// The values of the function's arguments. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool WriteFunctionArguments (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + Address function_address, + ValueList &arg_values, + Stream &errors); + + //------------------------------------------------------------------ + /// [Static] Execute a function, passing it a single void* parameter. + /// ClangFunction uses this to call the wrapper function. + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] function_address + /// The address of the function in the target process. + /// + /// @param[in] void_arg + /// The value of the void* parameter. + /// + /// @param[in] stop_others + /// True if other threads should pause during execution. + /// + /// @param[in] try_all_threads + /// If the timeout expires, true if other threads should run. If + /// the function may try to take locks, this is useful. + /// + /// @param[in] unwind_on_error + /// If true, and the execution stops before completion, we unwind the + /// function call, and return the program state to what it was before the + /// execution. If false, we leave the program in the stopped state. + /// + /// @param[in] timeout_usec + /// Timeout value (0 for no timeout). If try_all_threads is true, then we + /// will try on one thread for the lesser of .25 sec and half the total timeout. + /// then switch to running all threads, otherwise this will be the total timeout. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @param[in] this_arg + /// If non-NULL, the function is invoked like a C++ method, with the + /// value pointed to by the pointer as its 'this' argument. + /// + /// @return + /// Returns one of the ExecutionResults enum indicating function call status. + //------------------------------------------------------------------ + static ExecutionResults + ExecuteFunction (ExecutionContext &exe_ctx, + lldb::addr_t function_address, + lldb::addr_t &void_arg, + bool stop_others, + bool try_all_threads, + bool unwind_on_error, + bool ignore_breakpoints, + uint32_t timeout_usec, + Stream &errors, + lldb::addr_t* this_arg = 0); + + //------------------------------------------------------------------ + /// Run the function this ClangFunction was created with. + /// + /// This simple version will run the function stopping other threads + /// for a fixed timeout period (1000 usec) and if it does not complete, + /// we halt the process and try with all threads running. + /// + /// @param[in] exe_ctx + /// The thread & process in which this function will run. + /// + /// @param[in] errors + /// Errors will be written here if there are any. + /// + /// @param[out] results + /// The result value will be put here after running the function. + /// + /// @return + /// Returns one of the ExecutionResults enum indicating function call status. + //------------------------------------------------------------------ + ExecutionResults + ExecuteFunction(ExecutionContext &exe_ctx, + Stream &errors, + Value &results); + + //------------------------------------------------------------------ + /// Run the function this ClangFunction was created with. + /// + /// This simple version will run the function obeying the stop_others + /// argument. There is no timeout. + /// + /// @param[in] exe_ctx + /// The thread & process in which this function will run. + /// + /// @param[in] errors + /// Errors will be written here if there are any. + /// + /// @param[in] stop_others + /// If \b true, run only this thread, if \b false let all threads run. + /// + /// @param[out] results + /// The result value will be put here after running the function. + /// + /// @return + /// Returns one of the ExecutionResults enum indicating function call status. + //------------------------------------------------------------------ + ExecutionResults + ExecuteFunction(ExecutionContext &exe_ctx, + Stream &errors, bool stop_others, + Value &results); + + //------------------------------------------------------------------ + /// Run the function this ClangFunction was created with. + /// + /// This simple version will run the function on one thread. If \a timeout_usec + /// is not zero, we time out after that timeout. If \a try_all_threads is true, then we will + /// resume with all threads on, otherwise we halt the process, and eExecutionInterrupted will be returned. + /// + /// @param[in] exe_ctx + /// The thread & process in which this function will run. + /// + /// @param[in] errors + /// Errors will be written here if there are any. + /// + /// @param[in] timeout_usec + /// Timeout value (0 for no timeout). If try_all_threads is true, then we + /// will try on one thread for the lesser of .25 sec and half the total timeout. + /// then switch to running all threads, otherwise this will be the total timeout. + /// + /// @param[in] try_all_threads + /// If \b true, run only this thread, if \b false let all threads run. + /// + /// @param[out] results + /// The result value will be put here after running the function. + /// + /// @return + /// Returns one of the ExecutionResults enum indicating function call status. + //------------------------------------------------------------------ + ExecutionResults + ExecuteFunction(ExecutionContext &exe_ctx, + Stream &errors, + uint32_t single_thread_timeout_usec, + bool try_all_threads, + Value &results); + + //------------------------------------------------------------------ + /// Run the function this ClangFunction was created with. + /// + /// This is the full version. + /// + /// @param[in] exe_ctx + /// The thread & process in which this function will run. + /// + /// @param[in] args_addr_ptr + /// If NULL, the function will take care of allocating & deallocating the wrapper + /// args structure. Otherwise, if set to LLDB_INVALID_ADDRESS, a new structure + /// will be allocated, filled and the address returned to you. You are responsible + /// for deallocating it. And if passed in with a value other than LLDB_INVALID_ADDRESS, + /// this should point to an already allocated structure with the values already written. + /// + /// @param[in] errors + /// Errors will be written here if there are any. + /// + /// @param[in] stop_others + /// If \b true, run only this thread, if \b false let all threads run. + /// + /// @param[in] timeout_usec + /// Timeout value (0 for no timeout). If try_all_threads is true, then we + /// will try on one thread for the lesser of .25 sec and half the total timeout. + /// then switch to running all threads, otherwise this will be the total timeout. + /// + /// + /// @param[in] try_all_threads + /// If \b true, run only this thread, if \b false let all threads run. + /// + /// @param[out] results + /// The result value will be put here after running the function. + /// + /// @return + /// Returns one of the ExecutionResults enum indicating function call status. + //------------------------------------------------------------------ + ExecutionResults + ExecuteFunction(ExecutionContext &exe_ctx, + lldb::addr_t *args_addr_ptr, + Stream &errors, + bool stop_others, + uint32_t timeout_usec, + bool try_all_threads, + bool unwind_on_error, + bool ignore_breakpoints, + Value &results); + + //------------------------------------------------------------------ + /// [static] Get a thread plan to run a function. + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] func_addr + /// The address of the function in the target process. + /// + /// @param[in] args_addr_ref + /// The value of the void* parameter. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @param[in] stop_others + /// True if other threads should pause during execution. + /// + /// @param[in] unwind_on_error + /// True if the thread plan may simply be discarded if an error occurs. + /// + /// @param[in] ignore_breakpoints + /// True if the expression execution will ignore breakpoint hits and continue executing. + /// + /// @param[in] this_arg + /// If non-NULL (and cmd_arg is NULL), the function is invoked like a C++ + /// method, with the value pointed to by the pointer as its 'this' + /// argument. + /// + /// @param[in] cmd_arg + /// If non-NULL, the function is invoked like an Objective-C method, with + /// this_arg in the 'self' slot and cmd_arg in the '_cmd' slot + /// + /// @return + /// A ThreadPlan for executing the function. + //------------------------------------------------------------------ + static ThreadPlan * + GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, + lldb::addr_t func_addr, + lldb::addr_t &args_addr_ref, + Stream &errors, + bool stop_others, + bool unwind_on_error, + bool ignore_breakpoints, + lldb::addr_t *this_arg = 0, + lldb::addr_t *cmd_arg = 0); + + //------------------------------------------------------------------ + /// Get a thread plan to run the function this ClangFunction was created with. + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] func_addr + /// The address of the function in the target process. + /// + /// @param[in] args_addr_ref + /// The value of the void* parameter. + /// + /// @param[in] errors + /// The stream to write errors to. + /// + /// @param[in] stop_others + /// True if other threads should pause during execution. + /// + /// @param[in] unwind_on_error + /// True if the thread plan may simply be discarded if an error occurs. + /// + /// @return + /// A ThreadPlan for executing the function. + //------------------------------------------------------------------ + ThreadPlan * + GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, + lldb::addr_t &args_addr_ref, + Stream &errors, + bool stop_others, + bool unwind_on_error = true, + bool ignore_breakpoints = true) + { + return ClangFunction::GetThreadPlanToCallFunction (exe_ctx, + m_jit_start_addr, + args_addr_ref, + errors, + stop_others, + unwind_on_error, + ignore_breakpoints); + } + + //------------------------------------------------------------------ + /// Get the result of the function from its struct + /// + /// @param[in] exe_ctx + /// The execution context to retrieve the result from. + /// + /// @param[in] args_addr + /// The address of the argument struct. + /// + /// @param[in] ret_value + /// The value returned by the function. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool FetchFunctionResults (ExecutionContext &exe_ctx, + lldb::addr_t args_addr, + Value &ret_value); + + //------------------------------------------------------------------ + /// Deallocate the arguments structure + /// + /// @param[in] exe_ctx + /// The execution context to insert the function and its arguments + /// into. + /// + /// @param[in] args_addr + /// The address of the argument struct. + //------------------------------------------------------------------ + void DeallocateFunctionResults (ExecutionContext &exe_ctx, + lldb::addr_t args_addr); + + //------------------------------------------------------------------ + /// Interface for ClangExpression + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + const char * + Text () + { + return m_wrapper_function_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + const char * + FunctionName () + { + return m_wrapper_function_name.c_str(); + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap () + { + return NULL; + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when registering + /// local variables. May be NULL if the Expression doesn't care. + //------------------------------------------------------------------ + ClangExpressionVariableList * + LocalVariables () + { + return NULL; + } + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer (clang::ASTConsumer *passthrough); + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + bool + NeedsValidation () + { + return false; + } + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + bool + NeedsVariableResolution () + { + return false; + } + + ValueList + GetArgumentValues () const + { + return m_arg_values; + } +private: + //------------------------------------------------------------------ + // For ClangFunction only + //------------------------------------------------------------------ + + std::unique_ptr<ClangExpressionParser> m_parser; ///< The parser responsible for compiling the function. + std::unique_ptr<IRExecutionUnit> m_execution_unit_ap; + + Function *m_function_ptr; ///< The function we're going to call. May be NULL if we don't have debug info for the function. + Address m_function_addr; ///< If we don't have the FunctionSP, we at least need the address & return type. + ClangASTType m_function_return_type; ///< The opaque clang qual type for the function return type. + ClangASTContext *m_clang_ast_context; ///< This is the clang_ast_context that we're getting types from the and value, and the function return the function pointer is NULL. + + std::string m_wrapper_function_name; ///< The name of the wrapper function. + std::string m_wrapper_function_text; ///< The contents of the wrapper function. + std::string m_wrapper_struct_name; ///< The name of the struct that contains the target function address, arguments, and result. + std::list<lldb::addr_t> m_wrapper_args_addrs; ///< The addresses of the arguments to the wrapper function. + + bool m_struct_valid; ///< True if the ASTStructExtractor has populated the variables below. + + //------------------------------------------------------------------ + /// These values are populated by the ASTStructExtractor + size_t m_struct_size; ///< The size of the argument struct, in bytes. + std::vector<uint64_t> m_member_offsets; ///< The offset of each member in the struct, in bytes. + uint64_t m_return_size; ///< The size of the result variable, in bytes. + uint64_t m_return_offset; ///< The offset of the result variable in the struct, in bytes. + //------------------------------------------------------------------ + + ValueList m_arg_values; ///< The default values of the arguments. + + bool m_compiled; ///< True if the wrapper function has already been parsed. + bool m_JITted; ///< True if the wrapper function has already been JIT-compiled. +}; + +} // Namespace lldb_private + +#endif // lldb_ClangFunction_h_ diff --git a/include/lldb/Expression/ClangPersistentVariables.h b/include/lldb/Expression/ClangPersistentVariables.h new file mode 100644 index 0000000..6d9dae9 --- /dev/null +++ b/include/lldb/Expression/ClangPersistentVariables.h @@ -0,0 +1,75 @@ +//===-- ClangPersistentVariables.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_ClangPersistentVariables_h_ +#define liblldb_ClangPersistentVariables_h_ + +#include "lldb/Expression/ClangExpressionVariable.h" +#include "llvm/ADT/DenseMap.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h" +/// @brief Manages persistent values that need to be preserved between expression invocations. +/// +/// A list of variables that can be accessed and updated by any expression. See +/// ClangPersistentVariable for more discussion. Also provides an increasing, +/// 0-based counter for naming result variables. +//---------------------------------------------------------------------- +class ClangPersistentVariables : public ClangExpressionVariableList +{ +public: + + //---------------------------------------------------------------------- + /// Constructor + //---------------------------------------------------------------------- + ClangPersistentVariables (); + + lldb::ClangExpressionVariableSP + CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp); + + lldb::ClangExpressionVariableSP + CreatePersistentVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser& user_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size); + + //---------------------------------------------------------------------- + /// Return the next entry in the sequence of strings "$0", "$1", ... for + /// use naming persistent expression convenience variables. + /// + /// @return + /// A string that contains the next persistent variable name. + //---------------------------------------------------------------------- + ConstString + GetNextPersistentVariableName (); + + void + RemovePersistentVariable (lldb::ClangExpressionVariableSP variable); + + void + RegisterPersistentType (const ConstString &name, + clang::TypeDecl *tag_decl); + + clang::TypeDecl * + GetPersistentType (const ConstString &name); + +private: + uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). + + typedef llvm::DenseMap<const char *, clang::TypeDecl *> PersistentTypeMap; + PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user. +}; + +} + +#endif diff --git a/include/lldb/Expression/ClangUserExpression.h b/include/lldb/Expression/ClangUserExpression.h new file mode 100644 index 0000000..47bfebb --- /dev/null +++ b/include/lldb/Expression/ClangUserExpression.h @@ -0,0 +1,432 @@ +//===-- ClangUserExpression.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_ClangUserExpression_h_ +#define liblldb_ClangUserExpression_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/ClangExpression.h" +#include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/IRForTarget.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Target/ExecutionContext.h" + +#include "llvm/ExecutionEngine/JITMemoryManager.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUserExpression encapsulates +/// the objects needed to parse and interpret or JIT an expression. It +/// uses the Clang parser to produce LLVM IR from the expression. +//---------------------------------------------------------------------- +class ClangUserExpression : public ClangExpression +{ +public: + typedef std::shared_ptr<ClangUserExpression> ClangUserExpressionSP; + + enum { kDefaultTimeout = 500000u }; + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] expr + /// The expression to parse. + /// + /// @param[in] expr_prefix + /// If non-NULL, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in] language + /// If not eLanguageTypeUnknown, a language to use when parsing + /// the expression. Currently restricted to those languages + /// supported by Clang. + /// + /// @param[in] desired_type + /// If not eResultTypeAny, the type to use for the expression + /// result. + //------------------------------------------------------------------ + ClangUserExpression (const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual + ~ClangUserExpression (); + + //------------------------------------------------------------------ + /// Parse the expression + /// + /// @param[in] error_stream + /// A stream to print parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of functions, types of + /// variables, persistent variables, etc.) + /// + /// @param[in] execution_policy + /// Determines whether interpretation is possible or mandatory. + /// + /// @param[in] keep_result_in_memory + /// True if the resulting persistent variable should reside in + /// target memory, if applicable. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + bool + Parse (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory); + + bool + CanInterpret () + { + return m_can_interpret; + } + + bool + MatchesContext (ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Execute the parsed expression + /// + /// @param[in] error_stream + /// A stream to print errors to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of variables, etc.) + /// + /// @param[in] unwind_on_error + /// If true, and the execution stops before completion, we unwind the + /// function call, and return the program state to what it was before the + /// execution. If false, we leave the program in the stopped state. + /// + /// @param[in] ignore_breakpoints + /// If true, ignore breakpoints while executing the expression. + /// + /// @param[in] shared_ptr_to_me + /// This is a shared pointer to this ClangUserExpression. This is + /// needed because Execute can push a thread plan that will hold onto + /// the ClangUserExpression for an unbounded period of time. So you + /// need to give the thread plan a reference to this object that can + /// keep it alive. + /// + /// @param[in] result + /// A pointer to direct at the persistent variable in which the + /// expression's result is stored. + /// + /// @param[in] try_all_threads + /// If true, then we will try to run all threads if the function doesn't complete on + /// one thread. See timeout_usec for the interaction of this variable and + /// the timeout. + /// + /// @param[in] timeout_usec + /// Timeout value (0 for no timeout). If try_all_threads is true, then we + /// will try on one thread for the lesser of .25 sec and half the total timeout. + /// then switch to running all threads, otherwise this will be the total timeout. + /// + /// + /// @return + /// A Process::Execution results value. + //------------------------------------------------------------------ + ExecutionResults + Execute (Stream &error_stream, + ExecutionContext &exe_ctx, + bool unwind_on_error, + bool ignore_breakpoints, + ClangUserExpressionSP &shared_ptr_to_me, + lldb::ClangExpressionVariableSP &result, + bool try_all_threads, + uint32_t timeout_usec); + + ThreadPlan * + GetThreadPlanToExecuteJITExpression (Stream &error_stream, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Apply the side effects of the function to program state. + /// + /// @param[in] error_stream + /// A stream to print errors to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of variables, etc.) + /// + /// @param[in] result + /// A pointer to direct at the persistent variable in which the + /// expression's result is stored. + /// + /// @param[in] function_stack_pointer + /// A pointer to the base of the function's stack frame. This + /// is used to determine whether the expession result resides in + /// memory that will still be valid, or whether it needs to be + /// treated as homeless for the purpose of future expressions. + /// + /// @return + /// A Process::Execution results value. + //------------------------------------------------------------------ + bool + FinalizeJITExecution (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb::ClangExpressionVariableSP &result, + lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, + lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS); + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + const char * + Text () + { + return m_transformed_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the string that the user typed. + //------------------------------------------------------------------ + const char * + GetUserText () + { + return m_expr_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + const char * + FunctionName () + { + return "$__lldb_expr"; + } + + //------------------------------------------------------------------ + /// Return the language that should be used when parsing. To use + /// the default, return eLanguageTypeUnknown. + //------------------------------------------------------------------ + virtual lldb::LanguageType + Language () + { + return m_language; + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap () + { + return m_expr_decl_map.get(); + } + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer (clang::ASTConsumer *passthrough); + + //------------------------------------------------------------------ + /// Return the desired result type of the function, or + /// eResultTypeAny if indifferent. + //------------------------------------------------------------------ + virtual ResultType + DesiredResultType () + { + return m_desired_type; + } + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + bool + NeedsValidation () + { + return true; + } + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + bool + NeedsVariableResolution () + { + return true; + } + + //------------------------------------------------------------------ + /// Evaluate one expression and return its result. + /// + /// @param[in] exe_ctx + /// The execution context to use when evaluating the expression. + /// + /// @param[in] execution_policy + /// Determines whether or not to try using the IR interpreter to + /// avoid running the expression on the parser. + /// + /// @param[in] language + /// If not eLanguageTypeUnknown, a language to use when parsing + /// the expression. Currently restricted to those languages + /// supported by Clang. + /// + /// @param[in] unwind_on_error + /// True if the thread's state should be restored in the case + /// of an error. + /// + /// @param[in] ignore_breakpoints + /// If true, ignore breakpoints while executing the expression. + /// + /// @param[in] result_type + /// If not eResultTypeAny, the type of the desired result. Will + /// result in parse errors if impossible. + /// + /// @param[in] expr_cstr + /// A C string containing the expression to be evaluated. + /// + /// @param[in] expr_prefix + /// If non-NULL, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in/out] result_valobj_sp + /// If execution is successful, the result valobj is placed here. + /// + /// @param[in] try_all_threads + /// If true, then we will try to run all threads if the function doesn't complete on + /// one thread. See timeout_usec for the interaction of this variable and + /// the timeout. + /// + /// @param[in] timeout_usec + /// Timeout value (0 for no timeout). If try_all_threads is true, then we + /// will try on one thread for the lesser of .25 sec and half the total timeout. + /// then switch to running all threads, otherwise this will be the total timeout. + /// + /// @result + /// A Process::ExecutionResults value. eExecutionCompleted for success. + //------------------------------------------------------------------ + static ExecutionResults + Evaluate (ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + lldb::LanguageType language, + ResultType desired_type, + bool unwind_on_error, + bool ignore_breakpoints, + const char *expr_cstr, + const char *expr_prefix, + lldb::ValueObjectSP &result_valobj_sp, + bool try_all_threads, + uint32_t timeout_usec); + + static ExecutionResults + EvaluateWithError (ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + lldb::LanguageType language, + ResultType desired_type, + bool unwind_on_error, + bool ignore_breakpoints, + const char *expr_cstr, + const char *expr_prefix, + lldb::ValueObjectSP &result_valobj_sp, + Error &error, + bool try_all_threads, + uint32_t timeout_usec); + + static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression. +private: + //------------------------------------------------------------------ + /// Populate m_cplusplus and m_objetivec based on the environment. + //------------------------------------------------------------------ + + void + ScanContext (ExecutionContext &exe_ctx, + lldb_private::Error &err); + + bool + PrepareToExecuteJITExpression (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb::addr_t &struct_address, + lldb::addr_t &object_ptr, + lldb::addr_t &cmd_ptr); + + void + InstallContext (ExecutionContext &exe_ctx); + + bool + LockAndCheckContext (ExecutionContext &exe_ctx, + lldb::TargetSP &target_sp, + lldb::ProcessSP &process_sp, + lldb::StackFrameSP &frame_sp); + + lldb::ProcessWP m_process_wp; ///< The process used as the context for the expression. + Address m_address; ///< The address the process is stopped in. + lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame. + lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame. + + std::string m_expr_text; ///< The text of the expression, as typed by the user + std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user + lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults) + bool m_allow_cxx; ///< True if the language allows C++. + bool m_allow_objc; ///< True if the language allows Objective-C. + std::string m_transformed_text; ///< The text of the expression, as send to the parser + ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression. + + std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing the expression. + std::unique_ptr<IRExecutionUnit> m_execution_unit_ap; ///< The execution unit the expression is stored in. + std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use when running the expression. + std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer; ///< The result synthesizer, if one is needed. + + bool m_enforce_valid_object; ///< True if the expression parser should enforce the presence of a valid class pointer in order to generate the expression as a method. + bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method). + bool m_objectivec; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method). + bool m_static_method; ///< True if the expression is compiled as a static (or class) method (currently true if it was parsed when exe_ctx was in an Objective-C class method). + bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL. + bool m_const_object; ///< True if "this" is const. + Target *m_target; ///< The target for storing persistent data like types and variables. + + bool m_can_interpret; ///< True if the expression could be evaluated statically; false otherwise. + lldb::addr_t m_materialized_address; ///< The address at which the arguments to the expression have been materialized. + Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUserExpression_h_ diff --git a/include/lldb/Expression/ClangUtilityFunction.h b/include/lldb/Expression/ClangUtilityFunction.h new file mode 100644 index 0000000..6da8e5e --- /dev/null +++ b/include/lldb/Expression/ClangUtilityFunction.h @@ -0,0 +1,179 @@ +//===-- ClangUtilityFunction.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_ClangUtilityFunction_h_ +#define liblldb_ClangUtilityFunction_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/ClangExpression.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUtilityFunction encapsulates +/// a self-contained function meant to be used from other code. Utility +/// functions can perform error-checking for ClangUserExpressions, +//---------------------------------------------------------------------- +class ClangUtilityFunction : public ClangExpression +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] text + /// The text of the function. Must be a full translation unit. + /// + /// @param[in] name + /// The name of the function, as used in the text. + //------------------------------------------------------------------ + ClangUtilityFunction (const char *text, + const char *name); + + virtual + ~ClangUtilityFunction (); + + //------------------------------------------------------------------ + /// Install the utility function into a process + /// + /// @param[in] error_stream + /// A stream to print parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to install the utility function to. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + bool + Install (Stream &error_stream, ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Check whether the given PC is inside the function + /// + /// Especially useful if the function dereferences NULL to indicate a failed + /// assert. + /// + /// @param[in] pc + /// The program counter to check. + /// + /// @return + /// True if the program counter falls within the function's bounds; + /// false if not (or the function is not JIT compiled) + //------------------------------------------------------------------ + bool + ContainsAddress (lldb::addr_t address) + { + // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS, + // so this always returns false if the function is not JIT compiled yet + return (address >= m_jit_start_addr && address < m_jit_end_addr); + } + + + //------------------------------------------------------------------ + /// Return the string that the parser should parse. Must be a full + /// translation unit. + //------------------------------------------------------------------ + const char * + Text () + { + return m_function_text.c_str(); + } + + //------------------------------------------------------------------ + /// Return the function name that should be used for executing the + /// expression. Text() should contain the definition of this + /// function. + //------------------------------------------------------------------ + const char * + FunctionName () + { + return m_function_name.c_str(); + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap () + { + return m_expr_decl_map.get(); + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when registering + /// local variables. May be NULL if the Expression doesn't care. + //------------------------------------------------------------------ + ClangExpressionVariableList * + LocalVariables () + { + return NULL; + } + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer (clang::ASTConsumer *passthrough) + { + return NULL; + } + + //------------------------------------------------------------------ + /// Return true if validation code should be inserted into the + /// expression. + //------------------------------------------------------------------ + bool + NeedsValidation () + { + return false; + } + + //------------------------------------------------------------------ + /// Return true if external variables in the expression should be + /// resolved. + //------------------------------------------------------------------ + bool + NeedsVariableResolution () + { + return false; + } + +private: + std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression. + std::unique_ptr<IRExecutionUnit> m_execution_unit_ap; + + std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit. + std::string m_function_name; ///< The name of the function. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUtilityFunction_h_ diff --git a/include/lldb/Expression/DWARFExpression.h b/include/lldb/Expression/DWARFExpression.h new file mode 100644 index 0000000..2692831 --- /dev/null +++ b/include/lldb/Expression/DWARFExpression.h @@ -0,0 +1,424 @@ +//===-- DWARFExpression.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_DWARFExpression_h_ +#define liblldb_DWARFExpression_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Scalar.h" + +namespace lldb_private { + +class ClangExpressionVariable; +class ClangExpressionVariableList; + +class ClangExpressionDeclMap; + +//---------------------------------------------------------------------- +/// @class DWARFExpression DWARFExpression.h "lldb/Expression/DWARFExpression.h" +/// @brief Encapsulates a DWARF location expression and interprets it. +/// +/// DWARF location expressions are used in two ways by LLDB. The first +/// use is to find entities specified in the debug information, since +/// their locations are specified in precisely this language. The second +/// is to interpret expressions without having to run the target in cases +/// where the overhead from copying JIT-compiled code into the target is +/// too high or where the target cannot be run. This class encapsulates +/// a single DWARF location expression or a location list and interprets +/// it. +//---------------------------------------------------------------------- +class DWARFExpression +{ +public: + //------------------------------------------------------------------ + /// Constructor + //------------------------------------------------------------------ + DWARFExpression(); + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] data + /// A data extractor configured to read the DWARF location expression's + /// bytecode. + /// + /// @param[in] data_offset + /// The offset of the location expression in the extractor. + /// + /// @param[in] data_length + /// The byte length of the location expression. + //------------------------------------------------------------------ + DWARFExpression(const DataExtractor& data, + lldb::offset_t data_offset, + lldb::offset_t data_length); + + //------------------------------------------------------------------ + /// Copy constructor + //------------------------------------------------------------------ + DWARFExpression(const DWARFExpression& rhs); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual + ~DWARFExpression(); + + //------------------------------------------------------------------ + /// Print the description of the expression to a stream + /// + /// @param[in] s + /// The stream to print to. + /// + /// @param[in] level + /// The level of verbosity to use. + /// + /// @param[in] location_list_base_addr + /// If this is a location list based expression, this is the + /// address of the object that owns it. NOTE: this value is + /// different from the DWARF version of the location list base + /// address which is compile unit relative. This base address + /// is the address of the object that owns the location list. + /// + /// @param[in] abi + /// An optional ABI plug-in that can be used to resolve register + /// names. + //------------------------------------------------------------------ + void + GetDescription (Stream *s, + lldb::DescriptionLevel level, + lldb::addr_t location_list_base_addr, + ABI *abi) const; + + //------------------------------------------------------------------ + /// Return true if the location expression contains data + //------------------------------------------------------------------ + bool + IsValid() const; + + //------------------------------------------------------------------ + /// Return true if a location list was provided + //------------------------------------------------------------------ + bool + IsLocationList() const; + + //------------------------------------------------------------------ + /// Search for a load address in the location list + /// + /// @param[in] process + /// The process to use when resolving the load address + /// + /// @param[in] addr + /// The address to resolve + /// + /// @return + /// True if IsLocationList() is true and the address was found; + /// false otherwise. + //------------------------------------------------------------------ +// bool +// LocationListContainsLoadAddress (Process* process, const Address &addr) const; +// + bool + LocationListContainsAddress (lldb::addr_t loclist_base_addr, lldb::addr_t addr) const; + + //------------------------------------------------------------------ + /// If a location is not a location list, return true if the location + /// contains a DW_OP_addr () opcode in the stream that matches \a + /// file_addr. If file_addr is LLDB_INVALID_ADDRESS, the this + /// function will return true if the variable there is any DW_OP_addr + /// in a location that (yet still is NOT a location list). This helps + /// us detect if a variable is a global or static variable since + /// there is no other indication from DWARF debug info. + /// + /// @param[in] op_addr_idx + /// The DW_OP_addr index to retrieve in case there is more than + /// one DW_OP_addr opcode in the location byte stream. + /// + /// @param[out] error + /// If the location stream contains unknown DW_OP opcodes or the + /// data is missing, \a error will be set to \b true. + /// + /// @return + /// LLDB_INVALID_ADDRESS if the location doesn't contain a + /// DW_OP_addr for \a op_addr_idx, otherwise a valid file address + //------------------------------------------------------------------ + lldb::addr_t + GetLocation_DW_OP_addr (uint32_t op_addr_idx, bool &error) const; + + bool + Update_DW_OP_addr (lldb::addr_t file_addr); + + //------------------------------------------------------------------ + /// Make the expression parser read its location information from a + /// given data source. Does not change the offset and length + /// + /// @param[in] data + /// A data extractor configured to read the DWARF location expression's + /// bytecode. + //------------------------------------------------------------------ + void + SetOpcodeData(const DataExtractor& data); + + //------------------------------------------------------------------ + /// Make the expression parser read its location information from a + /// given data source + /// + /// @param[in] data + /// A data extractor configured to read the DWARF location expression's + /// bytecode. + /// + /// @param[in] data_offset + /// The offset of the location expression in the extractor. + /// + /// @param[in] data_length + /// The byte length of the location expression. + //------------------------------------------------------------------ + void + SetOpcodeData(const DataExtractor& data, lldb::offset_t data_offset, lldb::offset_t data_length); + + //------------------------------------------------------------------ + /// Copy the DWARF location expression into a local buffer. + /// + /// It is a good idea to copy the data so we don't keep the entire + /// object file worth of data around just for a few bytes of location + /// expression. LLDB typically will mmap the entire contents of debug + /// information files, and if we use SetOpcodeData, it will get a + /// shared reference to all of this data for the and cause the object + /// file to have to stay around. Even worse, a very very large ".a" + /// that contains one or more .o files could end up being referenced. + /// Location lists are typically small so even though we are copying + /// the data, it shouldn't amount to that much for the variables we + /// end up parsing. + /// + /// @param[in] data + /// A data extractor configured to read and copy the DWARF + /// location expression's bytecode. + /// + /// @param[in] data_offset + /// The offset of the location expression in the extractor. + /// + /// @param[in] data_length + /// The byte length of the location expression. + //------------------------------------------------------------------ + void + CopyOpcodeData (const DataExtractor& data, + lldb::offset_t data_offset, + lldb::offset_t data_length); + + + //------------------------------------------------------------------ + /// Tells the expression that it refers to a location list. + /// + /// @param[in] slide + /// This value should be a slide that is applied to any values + /// in the location list data so the values become zero based + /// offsets into the object that owns the location list. We need + /// to make location lists relative to the objects that own them + /// so we can relink addresses on the fly. + //------------------------------------------------------------------ + void + SetLocationListSlide (lldb::addr_t slide); + + //------------------------------------------------------------------ + /// Return the call-frame-info style register kind + //------------------------------------------------------------------ + int + GetRegisterKind (); + + //------------------------------------------------------------------ + /// Set the call-frame-info style register kind + /// + /// @param[in] reg_kind + /// The register kind. + //------------------------------------------------------------------ + void + SetRegisterKind (lldb::RegisterKind reg_kind); + + //------------------------------------------------------------------ + /// Wrapper for the static evaluate function that accepts an + /// ExecutionContextScope instead of an ExecutionContext and uses + /// member variables to populate many operands + //------------------------------------------------------------------ + bool + Evaluate (ExecutionContextScope *exe_scope, + ClangExpressionVariableList *expr_locals, + ClangExpressionDeclMap *decl_map, + lldb::addr_t loclist_base_load_addr, + const Value* initial_value_ptr, + Value& result, + Error *error_ptr) const; + + //------------------------------------------------------------------ + /// Wrapper for the static evaluate function that uses member + /// variables to populate many operands + //------------------------------------------------------------------ + bool + Evaluate (ExecutionContext *exe_ctx, + ClangExpressionVariableList *expr_locals, + ClangExpressionDeclMap *decl_map, + RegisterContext *reg_ctx, + lldb::addr_t loclist_base_load_addr, + const Value* initial_value_ptr, + Value& result, + Error *error_ptr) const; + + //------------------------------------------------------------------ + /// Evaluate a DWARF location expression in a particular context + /// + /// @param[in] exe_ctx + /// The execution context in which to evaluate the location + /// expression. The location expression may access the target's + /// memory, especially if it comes from the expression parser. + /// + /// @param[in] opcodes + /// This is a static method so the opcodes need to be provided + /// explicitly. + /// + /// @param[in] expr_locals + /// If the location expression was produced by the expression parser, + /// the list of local variables referenced by the DWARF expression. + /// This list should already have been populated during parsing; + /// the DWARF expression refers to variables by index. Can be NULL if + /// the location expression uses no locals. + /// + /// @param[in] decl_map + /// If the location expression was produced by the expression parser, + /// the list of external variables referenced by the location + /// expression. Can be NULL if the location expression uses no + /// external variables. + /// + /// @param[in] reg_ctx + /// An optional parameter which provides a RegisterContext for use + /// when evaluating the expression (i.e. for fetching register values). + /// Normally this will come from the ExecutionContext's StackFrame but + /// in the case where an expression needs to be evaluated while building + /// the stack frame list, this short-cut is available. + /// + /// @param[in] offset + /// The offset of the location expression in the data extractor. + /// + /// @param[in] length + /// The length in bytes of the location expression. + /// + /// @param[in] reg_set + /// The call-frame-info style register kind. + /// + /// @param[in] initial_value_ptr + /// A value to put on top of the interpreter stack before evaluating + /// the expression, if the expression is parametrized. Can be NULL. + /// + /// @param[in] result + /// A value into which the result of evaluating the expression is + /// to be placed. + /// + /// @param[in] error_ptr + /// If non-NULL, used to report errors in expression evaluation. + /// + /// @return + /// True on success; false otherwise. If error_ptr is non-NULL, + /// details of the failure are provided through it. + //------------------------------------------------------------------ + static bool + Evaluate (ExecutionContext *exe_ctx, + ClangExpressionVariableList *expr_locals, + ClangExpressionDeclMap *decl_map, + RegisterContext *reg_ctx, + const DataExtractor& opcodes, + const lldb::offset_t offset, + const lldb::offset_t length, + const uint32_t reg_set, + const Value* initial_value_ptr, + Value& result, + Error *error_ptr); + + //------------------------------------------------------------------ + /// Loads a ClangExpressionVariableList into the object + /// + /// @param[in] locals + /// If non-NULL, the list of locals used by this expression. + /// See Evaluate(). + //------------------------------------------------------------------ + void + SetExpressionLocalVariableList (ClangExpressionVariableList *locals); + + //------------------------------------------------------------------ + /// Loads a ClangExpressionDeclMap into the object + /// + /// @param[in] locals + /// If non-NULL, the list of external variables used by this + /// expression. See Evaluate(). + //------------------------------------------------------------------ + void + SetExpressionDeclMap (ClangExpressionDeclMap *decl_map); + + bool + GetExpressionData (DataExtractor &data) const + { + data = m_data; + return data.GetByteSize() > 0; + } + + bool + DumpLocationForAddress (Stream *s, + lldb::DescriptionLevel level, + lldb::addr_t loclist_base_load_addr, + lldb::addr_t address, + ABI *abi); + +protected: + //------------------------------------------------------------------ + /// Pretty-prints the location expression to a stream + /// + /// @param[in] stream + /// The stream to use for pretty-printing. + /// + /// @param[in] offset + /// The offset into the data buffer of the opcodes to be printed. + /// + /// @param[in] length + /// The length in bytes of the opcodes to be printed. + /// + /// @param[in] level + /// The level of detail to use in pretty-printing. + /// + /// @param[in] abi + /// An optional ABI plug-in that can be used to resolve register + /// names. + //------------------------------------------------------------------ + void + DumpLocation(Stream *s, + lldb::offset_t offset, + lldb::offset_t length, + lldb::DescriptionLevel level, + ABI *abi) const; + + bool + GetLocation (lldb::addr_t base_addr, + lldb::addr_t pc, + lldb::offset_t &offset, + lldb::offset_t &len); + + //------------------------------------------------------------------ + /// Classes that inherit from DWARFExpression can see and modify these + //------------------------------------------------------------------ + + DataExtractor m_data; ///< A data extractor capable of reading opcode bytes + lldb::RegisterKind m_reg_kind; ///< One of the defines that starts with LLDB_REGKIND_ + lldb::addr_t m_loclist_slide; ///< A value used to slide the location list offsets so that + ///< they are relative to the object that owns the location list + ///< (the function for frame base and variable location lists) + +}; + +} // namespace lldb_private + +#endif // liblldb_DWARFExpression_h_ diff --git a/include/lldb/Expression/ExpressionSourceCode.h b/include/lldb/Expression/ExpressionSourceCode.h new file mode 100644 index 0000000..be1014a --- /dev/null +++ b/include/lldb/Expression/ExpressionSourceCode.h @@ -0,0 +1,78 @@ +//===-- ExpressionSourceCode.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_ExpressionSourceCode_h +#define liblldb_ExpressionSourceCode_h + +#include "lldb/lldb-enumerations.h" + +#include <string> + +namespace lldb_private +{ + +class ExpressionSourceCode +{ +public: + static const char * g_expression_prefix; + + static ExpressionSourceCode *CreateWrapped (const char *prefix, + const char *body) + { + return new ExpressionSourceCode ("$__lldb_expr", + prefix, + body, + true); + } + + static ExpressionSourceCode *CreateUnwrapped (const char *name, + const char *body) + { + return new ExpressionSourceCode (name, + "", + body, + false); + } + + bool NeedsWrapping () const + { + return m_wrap; + } + + const char *GetName () const + { + return m_name.c_str(); + } + + bool GetText (std::string &text, + lldb::LanguageType wrapping_language, + bool const_object, + bool static_method) const; + +private: + ExpressionSourceCode (const char *name, + const char *prefix, + const char *body, + bool wrap) : + m_name(name), + m_prefix(prefix), + m_body(body), + m_wrap(wrap) + { + } + + std::string m_name; + std::string m_prefix; + std::string m_body; + bool m_wrap; +}; + +} // namespace lldb_private + +#endif diff --git a/include/lldb/Expression/IRDynamicChecks.h b/include/lldb/Expression/IRDynamicChecks.h new file mode 100644 index 0000000..226f5c9 --- /dev/null +++ b/include/lldb/Expression/IRDynamicChecks.h @@ -0,0 +1,169 @@ +//===-- IRDynamicChecks.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_IRDynamicChecks_h_ +#define liblldb_IRDynamicChecks_h_ + +#include "lldb/lldb-types.h" +#include "llvm/Pass.h" + +namespace llvm { + class BasicBlock; + class CallInst; + class Constant; + class Function; + class Instruction; + class Module; + class DataLayout; + class Value; +} + +namespace lldb_private +{ + +class ClangExpressionDeclMap; +class ClangUtilityFunction; +class ExecutionContext; +class Stream; + +//---------------------------------------------------------------------- +/// @class DynamicCheckerFunctions IRDynamicChecks.h "lldb/Expression/IRDynamicChecks.h" +/// @brief Encapsulates dynamic check functions used by expressions. +/// +/// Each of the utility functions encapsulated in this class is responsible +/// for validating some data that an expression is about to use. Examples are: +/// +/// a = *b; // check that b is a valid pointer +/// [b init]; // check that b is a valid object to send "init" to +/// +/// The class installs each checker function into the target process and +/// makes it available to IRDynamicChecks to use. +//---------------------------------------------------------------------- +class DynamicCheckerFunctions +{ +public: + //------------------------------------------------------------------ + /// Constructor + //------------------------------------------------------------------ + DynamicCheckerFunctions (); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~DynamicCheckerFunctions (); + + //------------------------------------------------------------------ + /// Install the utility functions into a process. This binds the + /// instance of DynamicCheckerFunctions to that process. + /// + /// @param[in] error_stream + /// A stream to print errors on. + /// + /// @param[in] exe_ctx + /// The execution context to install the functions into. + /// + /// @return + /// True on success; false on failure, or if the functions have + /// already been installed. + //------------------------------------------------------------------ + bool Install (Stream &error_stream, + ExecutionContext &exe_ctx); + + bool DoCheckersExplainStop (lldb::addr_t addr, Stream &message); + + std::unique_ptr<ClangUtilityFunction> m_valid_pointer_check; + std::unique_ptr<ClangUtilityFunction> m_objc_object_check; +}; + +//---------------------------------------------------------------------- +/// @class IRDynamicChecks IRDynamicChecks.h "lldb/Expression/IRDynamicChecks.h" +/// @brief Adds dynamic checks to a user-entered expression to reduce its likelihood of crashing +/// +/// When an IR function is executed in the target process, it may cause +/// crashes or hangs by dereferencing NULL pointers, trying to call Objective-C +/// methods on objects that do not respond to them, and so forth. +/// +/// IRDynamicChecks adds calls to the functions in DynamicCheckerFunctions +/// to appropriate locations in an expression's IR. +//---------------------------------------------------------------------- +class IRDynamicChecks : public llvm::ModulePass +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] checker_functions + /// The checker functions for the target process. + /// + /// @param[in] func_name + /// The name of the function to prepare for execution in the target. + /// + /// @param[in] decl_map + /// The mapping used to look up entities in the target process. In + /// this case, used to find objc_msgSend + //------------------------------------------------------------------ + IRDynamicChecks (DynamicCheckerFunctions &checker_functions, + const char* func_name = "$__lldb_expr"); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~IRDynamicChecks(); + + //------------------------------------------------------------------ + /// Run this IR transformer on a single module + /// + /// @param[in] M + /// The module to run on. This module is searched for the function + /// $__lldb_expr, and that function is passed to the passes one by + /// one. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool runOnModule(llvm::Module &M); + + //------------------------------------------------------------------ + /// Interface stub + //------------------------------------------------------------------ + void assignPassManager(llvm::PMStack &PMS, + llvm::PassManagerType T = llvm::PMT_ModulePassManager); + + //------------------------------------------------------------------ + /// Returns PMT_ModulePassManager + //------------------------------------------------------------------ + llvm::PassManagerType getPotentialPassManagerType() const; +private: + //------------------------------------------------------------------ + /// A basic block-level pass to find all pointer dereferences and + /// validate them before use. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] M + /// The module currently being processed. + /// + /// @param[in] BB + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool FindDataLoads(llvm::Module &M, + llvm::BasicBlock &BB); + + std::string m_func_name; ///< The name of the function to add checks to + DynamicCheckerFunctions &m_checker_functions; ///< The checker functions for the process +}; + +} + +#endif diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h new file mode 100644 index 0000000..885b651 --- /dev/null +++ b/include/lldb/Expression/IRExecutionUnit.h @@ -0,0 +1,495 @@ +//===-- IRExecutionUnit.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_IRExecutionUnit_h_ +#define lldb_IRExecutionUnit_h_ + +// C Includes +// C++ Includes +#include <atomic> +#include <string> +#include <vector> +#include <map> + +// Other libraries and framework includes +#include "llvm/IR/Module.h" + +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/DataBufferHeap.h" +#include "llvm/ExecutionEngine/JITMemoryManager.h" +#include "lldb/Expression/ClangExpression.h" +#include "lldb/Expression/ClangExpressionParser.h" +#include "lldb/Expression/IRMemoryMap.h" +#include "lldb/Host/Mutex.h" + +namespace llvm { + +class Module; +class ExecutionEngine; + +} + +namespace lldb_private { + +class Error; + +//---------------------------------------------------------------------- +/// @class IRExecutionUnit IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h" +/// @brief Contains the IR and, optionally, JIT-compiled code for a module. +/// +/// This class encapsulates the compiled version of an expression, in IR +/// form (for interpretation purposes) and in raw machine code form (for +/// execution in the target). +/// +/// This object wraps an IR module that comes from the expression parser, +/// and knows how to use the JIT to make it into executable code. It can +/// then be used as input to the IR interpreter, or the address of the +/// executable code can be passed to a thread plan to run in the target. +/// +/// This class creates a subclass of LLVM's JITMemoryManager, because that is +/// how the JIT emits code. Because LLDB needs to move JIT-compiled code +/// into the target process, the IRExecutionUnit knows how to copy the +/// emitted code into the target process. +//---------------------------------------------------------------------- +class IRExecutionUnit : public IRMemoryMap +{ +public: + //------------------------------------------------------------------ + /// Constructor + //------------------------------------------------------------------ + IRExecutionUnit (std::unique_ptr<llvm::LLVMContext> &context_ap, + std::unique_ptr<llvm::Module> &module_ap, + ConstString &name, + const lldb::TargetSP &target_sp, + std::vector<std::string> &cpu_features); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~IRExecutionUnit(); + + llvm::Module *GetModule() + { + return m_module; + } + + llvm::Function *GetFunction() + { + if (m_module) + return m_module->getFunction (m_name.AsCString()); + else + return NULL; + } + + void GetRunnableInfo(Error &error, + lldb::addr_t &func_addr, + lldb::addr_t &func_end); + + //------------------------------------------------------------------ + /// Accessors for IRForTarget and other clients that may want binary + /// data placed on their behalf. The binary data is owned by the + /// IRExecutionUnit unless the client explicitly chooses to free it. + //------------------------------------------------------------------ + + lldb::addr_t WriteNow(const uint8_t *bytes, + size_t size, + Error &error); + + void FreeNow(lldb::addr_t allocation); + +private: + //------------------------------------------------------------------ + /// Look up the object in m_address_map that contains a given address, + /// find where it was copied to, and return the remote address at the + /// same offset into the copied entity + /// + /// @param[in] local_address + /// The address in the debugger. + /// + /// @return + /// The address in the target process. + //------------------------------------------------------------------ + lldb::addr_t + GetRemoteAddressForLocal (lldb::addr_t local_address); + + //------------------------------------------------------------------ + /// Look up the object in m_address_map that contains a given address, + /// find where it was copied to, and return its address range in the + /// target process + /// + /// @param[in] local_address + /// The address in the debugger. + /// + /// @return + /// The range of the containing object in the target process. + //------------------------------------------------------------------ + typedef std::pair <lldb::addr_t, uintptr_t> AddrRange; + AddrRange + GetRemoteRangeForLocal (lldb::addr_t local_address); + + //------------------------------------------------------------------ + /// Commit all allocations to the process and record where they were stored. + /// + /// @param[in] process + /// The process to allocate memory in. + /// + /// @return + /// True <=> all allocations were performed successfully. + /// This method will attempt to free allocated memory if the + /// operation fails. + //------------------------------------------------------------------ + bool + CommitAllocations (lldb::ProcessSP &process_sp); + + //------------------------------------------------------------------ + /// Report all committed allocations to the execution engine. + /// + /// @param[in] engine + /// The execution engine to notify. + //------------------------------------------------------------------ + void + ReportAllocations (llvm::ExecutionEngine &engine); + + //------------------------------------------------------------------ + /// Write the contents of all allocations to the process. + /// + /// @param[in] local_address + /// The process containing the allocations. + /// + /// @return + /// True <=> all allocations were performed successfully. + //------------------------------------------------------------------ + bool + WriteData (lldb::ProcessSP &process_sp); + + Error + DisassembleFunction (Stream &stream, + lldb::ProcessSP &process_sp); + + class MemoryManager : public llvm::JITMemoryManager + { + public: + MemoryManager (IRExecutionUnit &parent); + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual void setMemoryWritable (); + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual void setMemoryExecutable (); + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual void setPoisonMemory (bool poison) + { + m_default_mm_ap->setPoisonMemory (poison); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual void AllocateGOT() + { + m_default_mm_ap->AllocateGOT(); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual uint8_t *getGOTBase() const + { + return m_default_mm_ap->getGOTBase(); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual uint8_t *startFunctionBody(const llvm::Function *F, + uintptr_t &ActualSize); + + //------------------------------------------------------------------ + /// Allocate room for a dyld stub for a lazy-referenced function, + /// and add it to the m_stubs map + /// + /// @param[in] F + /// The function being referenced. + /// + /// @param[in] StubSize + /// The size of the stub. + /// + /// @param[in] Alignment + /// The required alignment of the stub. + /// + /// @return + /// Allocated space for the stub. + //------------------------------------------------------------------ + virtual uint8_t *allocateStub(const llvm::GlobalValue* F, + unsigned StubSize, + unsigned Alignment); + + //------------------------------------------------------------------ + /// Complete the body of a function, and add it to the m_functions map + /// + /// @param[in] F + /// The function being completed. + /// + /// @param[in] FunctionStart + /// The first instruction of the function. + /// + /// @param[in] FunctionEnd + /// The last byte of the last instruction of the function. + //------------------------------------------------------------------ + virtual void endFunctionBody(const llvm::Function *F, + uint8_t *FunctionStart, + uint8_t *FunctionEnd); + //------------------------------------------------------------------ + /// Allocate space for an unspecified purpose, and add it to the + /// m_spaceBlocks map + /// + /// @param[in] Size + /// The size of the area. + /// + /// @param[in] Alignment + /// The required alignment of the area. + /// + /// @return + /// Allocated space. + //------------------------------------------------------------------ + virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment); + + //------------------------------------------------------------------ + /// Allocate space for executable code, and add it to the + /// m_spaceBlocks map + /// + /// @param[in] Size + /// The size of the area. + /// + /// @param[in] Alignment + /// The required alignment of the area. + /// + /// @param[in] SectionID + /// A unique identifier for the section. + /// + /// @return + /// Allocated space. + //------------------------------------------------------------------ + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID); + + //------------------------------------------------------------------ + /// Allocate space for data, and add it to the m_spaceBlocks map + /// + /// @param[in] Size + /// The size of the area. + /// + /// @param[in] Alignment + /// The required alignment of the area. + /// + /// @param[in] SectionID + /// A unique identifier for the section. + /// + /// @param[in] IsReadOnly + /// Flag indicating the section is read-only. + /// + /// @return + /// Allocated space. + //------------------------------------------------------------------ + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, bool IsReadOnly); + + //------------------------------------------------------------------ + /// Allocate space for a global variable, and add it to the + /// m_spaceBlocks map + /// + /// @param[in] Size + /// The size of the variable. + /// + /// @param[in] Alignment + /// The required alignment of the variable. + /// + /// @return + /// Allocated space for the global. + //------------------------------------------------------------------ + virtual uint8_t *allocateGlobal(uintptr_t Size, + unsigned Alignment); + + //------------------------------------------------------------------ + /// Called when object loading is complete and section page + /// permissions can be applied. Currently unimplemented for LLDB. + /// + /// @param[out] ErrMsg + /// The error that prevented the page protection from succeeding. + /// + /// @return + /// True in case of failure, false in case of success. + //------------------------------------------------------------------ + virtual bool finalizeMemory(std::string *ErrMsg) { + // TODO: Ensure that the instruction cache is flushed because + // relocations are updated by dy-load. See: + // sys::Memory::InvalidateInstructionCache + // llvm::SectionMemoryManager + return false; + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual void deallocateFunctionBody(void *Body); + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual size_t GetDefaultCodeSlabSize() { + return m_default_mm_ap->GetDefaultCodeSlabSize(); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual size_t GetDefaultDataSlabSize() { + return m_default_mm_ap->GetDefaultDataSlabSize(); + } + + virtual size_t GetDefaultStubSlabSize() { + return m_default_mm_ap->GetDefaultStubSlabSize(); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual unsigned GetNumCodeSlabs() { + return m_default_mm_ap->GetNumCodeSlabs(); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual unsigned GetNumDataSlabs() { + return m_default_mm_ap->GetNumDataSlabs(); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual unsigned GetNumStubSlabs() { + return m_default_mm_ap->GetNumStubSlabs(); + } + + //------------------------------------------------------------------ + /// Passthrough interface stub + //------------------------------------------------------------------ + virtual void *getPointerToNamedFunction(const std::string &Name, + bool AbortOnFailure = true) { + return m_default_mm_ap->getPointerToNamedFunction(Name, AbortOnFailure); + } + private: + std::unique_ptr<JITMemoryManager> m_default_mm_ap; ///< The memory allocator to use in actually creating space. All calls are passed through to it. + IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. + }; + + //---------------------------------------------------------------------- + /// @class JittedFunction IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h" + /// @brief Encapsulates a single function that has been generated by the JIT. + /// + /// Functions that have been generated by the JIT are first resident in the + /// local process, and then placed in the target process. JittedFunction + /// represents a function possibly resident in both. + //---------------------------------------------------------------------- + struct JittedFunction { + std::string m_name; ///< The function's name + lldb::addr_t m_local_addr; ///< The address of the function in LLDB's memory + lldb::addr_t m_remote_addr; ///< The address of the function in the target's memory + + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variabes. + /// + /// @param[in] name + /// The name of the function. + /// + /// @param[in] local_addr + /// The address of the function in LLDB, or LLDB_INVALID_ADDRESS if + /// it is not present in LLDB's memory. + /// + /// @param[in] remote_addr + /// The address of the function in the target, or LLDB_INVALID_ADDRESS + /// if it is not present in the target's memory. + //------------------------------------------------------------------ + JittedFunction (const char *name, + lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, + lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) : + m_name (name), + m_local_addr (local_addr), + m_remote_addr (remote_addr) + { + } + }; + + static const unsigned eSectionIDInvalid = (unsigned)-1; + + //---------------------------------------------------------------------- + /// @class AllocationRecord IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h" + /// @brief Enacpsulates a single allocation request made by the JIT. + /// + /// Allocations made by the JIT are first queued up and then applied in + /// bulk to the underlying process. + //---------------------------------------------------------------------- + struct AllocationRecord { + lldb::addr_t m_process_address; + uintptr_t m_host_address; + uint32_t m_permissions; + size_t m_size; + unsigned m_alignment; + unsigned m_section_id; + + AllocationRecord (uintptr_t host_address, + uint32_t permissions, + size_t size, + unsigned alignment, + unsigned section_id = eSectionIDInvalid) : + m_process_address(LLDB_INVALID_ADDRESS), + m_host_address(host_address), + m_permissions(permissions), + m_size(size), + m_alignment(alignment), + m_section_id(section_id) + { + } + + void dump (Log *log); + }; + + typedef std::vector<AllocationRecord> RecordVector; + RecordVector m_records; + + std::unique_ptr<llvm::LLVMContext> m_context_ap; + std::unique_ptr<llvm::ExecutionEngine> m_execution_engine_ap; + std::unique_ptr<llvm::Module> m_module_ap; ///< Holder for the module until it's been handed off + llvm::Module *m_module; ///< Owned by the execution engine + std::vector<std::string> m_cpu_features; + llvm::SmallVector<JittedFunction, 1> m_jitted_functions; ///< A vector of all functions that have been JITted into machine code + const ConstString m_name; + + std::atomic<bool> m_did_jit; + + lldb::addr_t m_function_load_addr; + lldb::addr_t m_function_end_load_addr; +}; + +} // namespace lldb_private + +#endif // lldb_IRExecutionUnit_h_ diff --git a/include/lldb/Expression/IRForTarget.h b/include/lldb/Expression/IRForTarget.h new file mode 100644 index 0000000..151bf2a --- /dev/null +++ b/include/lldb/Expression/IRForTarget.h @@ -0,0 +1,733 @@ +//===-- IRForTarget.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_IRForTarget_h_ +#define liblldb_IRForTarget_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "llvm/Pass.h" + +#include <map> + +namespace llvm { + class BasicBlock; + class CallInst; + class Constant; + class ConstantInt; + class Function; + class GlobalValue; + class GlobalVariable; + class Instruction; + class Module; + class StoreInst; + class DataLayout; + class Type; + class Value; +} + +namespace lldb_private { + class ClangExpressionDeclMap; + class IRExecutionUnit; + class IRMemoryMap; +} + +//---------------------------------------------------------------------- +/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" +/// @brief Transforms the IR for a function to run in the target +/// +/// Once an expression has been parsed and converted to IR, it can run +/// in two contexts: interpreted by LLDB as a DWARF location expression, +/// or compiled by the JIT and inserted into the target process for +/// execution. +/// +/// IRForTarget makes the second possible, by applying a series of +/// transformations to the IR which make it relocatable. These +/// transformations are discussed in more detail next to their relevant +/// functions. +//---------------------------------------------------------------------- +class IRForTarget : public llvm::ModulePass +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] decl_map + /// The list of externally-referenced variables for the expression, + /// for use in looking up globals and allocating the argument + /// struct. See the documentation for ClangExpressionDeclMap. + /// + /// @param[in] resolve_vars + /// True if the external variable references (including persistent + /// variables) should be resolved. If not, only external functions + /// are resolved. + /// + /// @param[in] execution_policy + /// Determines whether an IR interpreter can be used to statically + /// evaluate the expression. + /// + /// @param[in] const_result + /// This variable is populated with the statically-computed result + /// of the function, if it has no side-effects and the result can + /// be computed statically. + /// + /// @param[in] execution_unit + /// The holder for raw data associated with the expression. + /// + /// @param[in] error_stream + /// If non-NULL, a stream on which errors can be printed. + /// + /// @param[in] func_name + /// The name of the function to prepare for execution in the target. + //------------------------------------------------------------------ + IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, + bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream *error_stream, + const char* func_name = "$__lldb_expr"); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~IRForTarget(); + + //------------------------------------------------------------------ + /// Run this IR transformer on a single module + /// + /// Implementation of the llvm::ModulePass::runOnModule() function. + /// + /// @param[in] llvm_module + /// The module to run on. This module is searched for the function + /// $__lldb_expr, and that function is passed to the passes one by + /// one. + /// + /// @param[in] interpreter_error + /// An error. If the expression fails to be interpreted, this error + /// is set to a reason why. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + virtual bool + runOnModule (llvm::Module &llvm_module); + + //------------------------------------------------------------------ + /// Interface stub + /// + /// Implementation of the llvm::ModulePass::assignPassManager() + /// function. + //------------------------------------------------------------------ + virtual void + assignPassManager (llvm::PMStack &pass_mgr_stack, + llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager); + + //------------------------------------------------------------------ + /// Returns PMT_ModulePassManager + /// + /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() + /// function. + //------------------------------------------------------------------ + virtual llvm::PassManagerType + getPotentialPassManagerType() const; + +private: + //------------------------------------------------------------------ + /// Ensures that the current function's linkage is set to external. + /// Otherwise the JIT may not return an address for it. + /// + /// @param[in] llvm_function + /// The function whose linkage is to be fixed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + FixFunctionLinkage (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to replace all function pointers with their + /// integer equivalents. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + HasSideEffects (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A function-level pass to check whether the function has side + /// effects. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Get the address of a fuction, and a location to put the complete + /// Value of the function if one is available. + /// + /// @param[in] function + /// The function to find the location of. + /// + /// @param[out] ptr + /// The location of the function in the target. + /// + /// @param[out] name + /// The resolved name of the function (matters for intrinsics). + /// + /// @param[out] value_ptr + /// A variable to put the function's completed Value* in, or NULL + /// if the Value* shouldn't be stored anywhere. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + bool + GetFunctionAddress (llvm::Function *function, + uint64_t &ptr, + lldb_private::ConstString &name, + llvm::Constant **&value_ptr); + + //------------------------------------------------------------------ + /// Build a function pointer given a type and a raw pointer. + /// + /// @param[in] type + /// The type of the function pointer to be built. + /// + /// @param[in] ptr + /// The value of the pointer. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + llvm::Constant * + BuildFunctionPointer (llvm::Type *type, + uint64_t ptr); + + void + RegisterFunctionMetadata (llvm::LLVMContext &context, + llvm::Value *function_ptr, + const char *name); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True if the function has side effects (or if this cannot + /// be determined); false otherwise. + //------------------------------------------------------------------ + bool + ResolveFunctionPointers (llvm::Module &llvm_module); + + //------------------------------------------------------------------ + /// A function-level pass to take the generated global value + /// $__lldb_expr_result and make it into a persistent variable. + /// Also see ASTResultSynthesizer. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Find the NamedDecl corresponding to a Value. This interface is + /// exposed for the IR interpreter. + /// + /// @param[in] module + /// The module containing metadata to search + /// + /// @param[in] global + /// The global entity to search for + /// + /// @return + /// The corresponding variable declaration + //------------------------------------------------------------------ +public: + static clang::NamedDecl * + DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); +private: + clang::NamedDecl * + DeclForGlobal (llvm::GlobalValue *global); + + //------------------------------------------------------------------ + /// Set the constant result variable m_const_result to the provided + /// constant, assuming it can be evaluated. The result variable + /// will be reset to NULL later if the expression has side effects. + /// + /// @param[in] initializer + /// The constant initializer for the variable. + /// + /// @param[in] name + /// The name of the result variable. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetConstantResult (llvm::Constant *initializer, + const lldb_private::ConstString &name, + lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// If the IR represents a cast of a variable, set m_const_result + /// to the result of the cast. The result variable will be reset to + /// NULL latger if the expression has side effects. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetCastResult (lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CreateResultVariable (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to find Objective-C constant strings and + /// transform them to calls to CFStringCreateWithBytes. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a single Objective-C constant string. + /// + /// @param[in] NSStr + /// The constant NSString to be transformed + /// + /// @param[in] CStr + /// The constant C string inside the NSString. This will be + /// passed as the bytes argument to CFStringCreateWithBytes. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstString (llvm::GlobalVariable *NSStr, + llvm::GlobalVariable *CStr); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstStrings (); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all Objective-C method calls and + /// rewrite them to use sel_registerName instead of statically allocated + /// selectors. The reason is that the selectors are created on the + /// assumption that the Objective-C runtime will scan the appropriate + /// section and prepare them. This doesn't happen when code is copied + /// into the target, though, and there's no easy way to induce the + /// runtime to scan them. So instead we get our selectors from + /// sel_registerName. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Replace a single selector reference + /// + /// @param[in] selector_load + /// The load of the statically-allocated selector. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelector (llvm::Instruction* selector_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelectors (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all newly-declared persistent + /// variables and register them with the ClangExprDeclMap. This + /// allows them to be materialized and dematerialized like normal + /// external variables. Before transformation, these persistent + /// variables look like normal locals, so they have an allocation. + /// This pass excises these allocations and makes references look + /// like external references where they will be resolved -- like all + /// other external references -- by ResolveExternals(). + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Handle a single allocation of a persistent variable + /// + /// @param[in] persistent_alloc + /// The allocation of the persistent variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewritePersistentAlloc (llvm::Instruction *persistent_alloc); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + //------------------------------------------------------------------ + bool + RewritePersistentAllocs (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to find all external variables and functions + /// used in the IR. Each found external variable is added to the + /// struct, and each external function is resolved in place, its call + /// replaced with a call to a function pointer whose value is the + /// address of the function in the target process. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Write an initializer to a memory array of assumed sufficient + /// size. + /// + /// @param[in] data + /// A pointer to the data to write to. + /// + /// @param[in] initializer + /// The initializer itself. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); + + //------------------------------------------------------------------ + /// Move an internal variable into the static allocation section. + /// + /// @param[in] global_variable + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInternalVariable (llvm::GlobalVariable *global_variable); + + //------------------------------------------------------------------ + /// Handle a single externally-defined variable + /// + /// @param[in] value + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleVariable (llvm::Value *value); + + //------------------------------------------------------------------ + /// Handle a single externally-defined symbol + /// + /// @param[in] symbol + /// The symbol. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleSymbol (llvm::Value *symbol); + + //------------------------------------------------------------------ + /// Handle a single externally-defined Objective-C class + /// + /// @param[in] classlist_reference + /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" + /// where n (if present) is an index. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleObjCClass(llvm::Value *classlist_reference); + + //------------------------------------------------------------------ + /// Handle all the arguments to a function call + /// + /// @param[in] C + /// The call instruction. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleCallArguments (llvm::CallInst *call_inst); + + //------------------------------------------------------------------ + /// Resolve variable references in calls to external functions + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveCalls (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// Remove calls to __cxa_atexit, which should never be generated by + /// expressions. + /// + /// @param[in] call_inst + /// The call instruction. + /// + /// @return + /// True if the scan was successful; false if some operation + /// failed + //------------------------------------------------------------------ + bool + RemoveCXAAtExit (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveExternals (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A basic block-level pass to excise guard variables from the code. + /// The result for the function is passed through Clang as a static + /// variable. Static variables normally have guard variables to + /// ensure that they are only initialized once. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a load to a guard variable to return constant 0. + /// + /// @param[in] guard_load + /// The load instruction to zero out. + //------------------------------------------------------------------ + void + TurnGuardLoadIntoZero(llvm::Instruction* guard_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RemoveGuards (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A module-level pass to allocate all string literals in a separate + /// allocation and redirect references to them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStrings (); + + //------------------------------------------------------------------ + /// A basick block-level pass to find all literals that will be + /// allocated as statics by the JIT (in contrast to the Strings, + /// which already are statics) and synthesize loads for them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStaticLiterals (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to make all external variable references + /// point at the correct offsets from the void* passed into the + /// function. ClangExpressionDeclMap::DoStructLayout() must be called + /// beforehand, so that the offsets are valid. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceVariables (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to remove all global variables from the + /// module since it no longer should export or import any symbols. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + StripAllGVs (llvm::Module &llvm_module); + + class StaticDataAllocator { + public: + StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit); + lldb_private::StreamString &GetStream() + { + return m_stream_string; + } + lldb::addr_t Allocate(); + private: + lldb_private::IRExecutionUnit &m_execution_unit; + lldb_private::StreamString m_stream_string; + lldb::addr_t m_allocation; + }; + + /// Flags + bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved + std::string m_func_name; ///< The name of the function to translate + lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...) + lldb_private::TypeFromParser m_result_type; ///< The type of the result variable. + llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. + std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the module being processed, or NULL if there is no module. + lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls + StaticDataAllocator m_data_allocator; ///< The allocator to use for constant strings + llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type + llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type + lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed + + llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL. + bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) + + llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final location of the static allocation. + + //------------------------------------------------------------------ + /// UnfoldConstant operates on a constant [Old] which has just been + /// replaced with a value [New]. We assume that new_value has + /// been properly placed early in the function, in front of the + /// first instruction in the entry basic block + /// [FirstEntryInstruction]. + /// + /// UnfoldConstant reads through the uses of Old and replaces Old + /// in those uses with New. Where those uses are constants, the + /// function generates new instructions to compute the result of the + /// new, non-constant expression and places them before + /// FirstEntryInstruction. These instructions replace the constant + /// uses, so UnfoldConstant calls itself recursively for those. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + + class FunctionValueCache { + public: + typedef std::function <llvm::Value *(llvm::Function *)> Maker; + + FunctionValueCache (Maker const &maker); + ~FunctionValueCache (); + llvm::Value *GetValue (llvm::Function *function); + private: + Maker const m_maker; + typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap; + FunctionValueMap m_values; + }; + + FunctionValueCache m_entry_instruction_finder; + + static bool + UnfoldConstant (llvm::Constant *old_constant, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder); + + //------------------------------------------------------------------ + /// Construct a reference to m_reloc_placeholder with a given type + /// and offset. This typically happens after inserting data into + /// m_data_allocator. + /// + /// @param[in] type + /// The type of the value being loaded. + /// + /// @param[in] offset + /// The offset of the value from the base of m_data_allocator. + /// + /// @return + /// The Constant for the reference, usually a ConstantExpr. + //------------------------------------------------------------------ + llvm::Constant * + BuildRelocation(llvm::Type *type, + uint64_t offset); + + //------------------------------------------------------------------ + /// Commit the allocation in m_data_allocator and use its final + /// location to replace m_reloc_placeholder. + /// + /// @param[in] module + /// The module that m_data_allocator resides in + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CompleteDataAllocation (); + +}; + +#endif diff --git a/include/lldb/Expression/IRInterpreter.h b/include/lldb/Expression/IRInterpreter.h new file mode 100644 index 0000000..5defa8d --- /dev/null +++ b/include/lldb/Expression/IRInterpreter.h @@ -0,0 +1,64 @@ +//===-- IRInterpreter.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_IRInterpreter_h_ +#define liblldb_IRInterpreter_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Stream.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Pass.h" + +namespace llvm { + class Function; + class Module; +} + +namespace lldb_private { + +class ClangExpressionDeclMap; +class IRMemoryMap; + +} + +//---------------------------------------------------------------------- +/// @class IRInterpreter IRInterpreter.h "lldb/Expression/IRInterpreter.h" +/// @brief Attempt to interpret the function's code if it does not require +/// running the target. +/// +/// In some cases, the IR for an expression can be evaluated entirely +/// in the debugger, manipulating variables but not executing any code +/// in the target. The IRInterpreter attempts to do this. +//---------------------------------------------------------------------- +class IRInterpreter +{ +public: + static bool + CanInterpret (llvm::Module &module, + llvm::Function &function, + lldb_private::Error &error); + + static bool + Interpret (llvm::Module &module, + llvm::Function &function, + llvm::ArrayRef<lldb::addr_t> args, + lldb_private::IRMemoryMap &memory_map, + lldb_private::Error &error, + lldb::addr_t stack_frame_bottom, + lldb::addr_t stack_frame_top); + +private: + static bool + supportsFunction (llvm::Function &llvm_function, + lldb_private::Error &err); +}; + +#endif diff --git a/include/lldb/Expression/IRMemoryMap.h b/include/lldb/Expression/IRMemoryMap.h new file mode 100644 index 0000000..affe193 --- /dev/null +++ b/include/lldb/Expression/IRMemoryMap.h @@ -0,0 +1,126 @@ +//===-- IRExecutionUnit.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_IRMemoryMap_h_ +#define lldb_IRMemoryMap_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/UserID.h" + +#include <map> + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h" +/// @brief Encapsulates memory that may exist in the process but must +/// also be available in the host process. +/// +/// This class encapsulates a group of memory objects that must be readable +/// or writable from the host process regardless of whether the process +/// exists. This allows the IR interpreter as well as JITted code to access +/// the same memory. +/// +/// Point queries against this group of memory objects can be made by the +/// address in the tar at which they reside. If the inferior does not +/// exist, allocations still get made-up addresses. If an inferior appears +/// at some point, then those addresses need to be re-mapped. +//---------------------------------------------------------------------- +class IRMemoryMap +{ +public: + IRMemoryMap (lldb::TargetSP target_sp); + ~IRMemoryMap (); + + enum AllocationPolicy { + eAllocationPolicyInvalid = 0, ///< It is an error for an allocation to have this policy. + eAllocationPolicyHostOnly, ///< This allocation was created in the host and will never make it into the process. + ///< It is an error to create other types of allocations while such allocations exist. + eAllocationPolicyMirror, ///< The intent is that this allocation exist both in the host and the process and have + ///< the same content in both. + eAllocationPolicyProcessOnly ///< The intent is that this allocation exist only in the process. + }; + + lldb::addr_t Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error); + void Leak (lldb::addr_t process_address, Error &error); + void Free (lldb::addr_t process_address, Error &error); + + void WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error); + void WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error); + void WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error); + void ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error); + void ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error); + void ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error); + + void GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error); + + lldb::ByteOrder GetByteOrder(); + uint32_t GetAddressByteSize(); + + // This function can return NULL. + ExecutionContextScope *GetBestExecutionContextScope(); + +protected: + // This function should only be used if you know you are using the JIT. + // Any other cases should use GetBestExecutionContextScope(). + lldb::ProcessWP GetProcessWP () + { + return m_process_wp; + } + +private: + struct Allocation + { + lldb::addr_t m_process_alloc; ///< The (unaligned) base for the remote allocation + lldb::addr_t m_process_start; ///< The base address of the allocation in the process + size_t m_size; ///< The size of the requested allocation + uint32_t m_permissions; ///< The access permissions on the memory in the process. In the host, the memory is always read/write. + uint8_t m_alignment; ///< The alignment of the requested allocation + DataBufferHeap m_data; + + ///< Flags + AllocationPolicy m_policy; + bool m_leak; + public: + Allocation (lldb::addr_t process_alloc, + lldb::addr_t process_start, + size_t size, + uint32_t permissions, + uint8_t alignment, + AllocationPolicy m_policy); + + Allocation () : + m_process_alloc (LLDB_INVALID_ADDRESS), + m_process_start (LLDB_INVALID_ADDRESS), + m_size (0), + m_permissions (0), + m_alignment (0), + m_data (), + m_policy (eAllocationPolicyInvalid), + m_leak (false) + { + } + }; + + lldb::ProcessWP m_process_wp; + lldb::TargetWP m_target_wp; + typedef std::map<lldb::addr_t, Allocation> AllocationMap; + AllocationMap m_allocations; + + lldb::addr_t FindSpace (size_t size); + bool ContainsHostOnlyAllocations (); + AllocationMap::iterator FindAllocation (lldb::addr_t addr, size_t size); + bool IntersectsAllocation (lldb::addr_t addr, size_t size); +}; + +} + +#endif diff --git a/include/lldb/Expression/IRToDWARF.h b/include/lldb/Expression/IRToDWARF.h new file mode 100644 index 0000000..43dc99d --- /dev/null +++ b/include/lldb/Expression/IRToDWARF.h @@ -0,0 +1,111 @@ +//===-- IRToDWARF.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_IRToDWARF_h_ +#define liblldb_IRToDWARF_h_ + +#include "llvm/Pass.h" +#include "llvm/PassManager.h" + +#include "lldb/lldb-public.h" + +class Relocator; +//---------------------------------------------------------------------- +/// @class IRToDWARF IRToDWARF.h "lldb/Expression/IRToDWARF.h" +/// @brief Transforms the IR for a function into a DWARF location expression +/// +/// Once an expression has been parsed and converted to IR, it can run +/// in two contexts: interpreted by LLDB as a DWARF location expression, +/// or compiled by the JIT and inserted into the target process for +/// execution. +/// +/// IRToDWARF makes the first possible, by traversing the control flow +/// graph and writing the code for each basic block out as location +/// expression bytecode. To ensure that the links between the basic blocks +/// remain intact, it uses a relocator that records the location of every +/// location expression instruction that has a relocatable operand, the +/// target of that operand (as a basic block), and the mapping of each basic +/// block to an actual location. After all code has been written out, the +/// relocator post-processes it and performs all necessary relocations. +//---------------------------------------------------------------------- +class IRToDWARF : public llvm::ModulePass +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] local_vars + /// A list of variables to populate with the local variables this + /// expression uses. + /// + /// @param[in] decl_map + /// The list of externally-referenced variables for the expression, + /// for use in looking up globals. + /// + /// @param[in] stream + /// The stream to dump DWARF bytecode onto. + /// + /// @param[in] func_name + /// The name of the function to translate to DWARF. + //------------------------------------------------------------------ + IRToDWARF(lldb_private::ClangExpressionVariableList &local_vars, + lldb_private::ClangExpressionDeclMap *decl_map, + lldb_private::StreamString &strm, + const char* func_name = "$__lldb_expr"); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~IRToDWARF(); + + //------------------------------------------------------------------ + /// Run this IR transformer on a single module + /// + /// @param[in] M + /// The module to run on. This module is searched for the function + /// $__lldb_expr, and that function is converted to a location + /// expression. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool runOnModule(llvm::Module &M); + + //------------------------------------------------------------------ + /// Interface stub + //------------------------------------------------------------------ + void assignPassManager(llvm::PMStack &PMS, + llvm::PassManagerType T = llvm::PMT_ModulePassManager); + + //------------------------------------------------------------------ + /// Returns PMT_ModulePassManager + //------------------------------------------------------------------ + llvm::PassManagerType getPotentialPassManagerType() const; +private: + //------------------------------------------------------------------ + /// Run this IR transformer on a single basic block + /// + /// @param[in] BB + /// The basic block to transform. + /// + /// @param[in] Relocator + /// The relocator to use when registering branches. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool runOnBasicBlock(llvm::BasicBlock &BB, Relocator &Relocator); + + std::string m_func_name; ///< The name of the function to translate + lldb_private::ClangExpressionVariableList &m_local_vars; ///< The list of local variables to populate while transforming + lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The list of external variables + lldb_private::StreamString &m_strm; ///< The stream to write bytecode to +}; + +#endif diff --git a/include/lldb/Expression/Materializer.h b/include/lldb/Expression/Materializer.h new file mode 100644 index 0000000..208a081 --- /dev/null +++ b/include/lldb/Expression/Materializer.h @@ -0,0 +1,173 @@ +//===-- Materializer.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_Materializer_h +#define lldb_Materializer_h + +#include "lldb/lldb-private-types.h" +#include "lldb/Core/Error.h" +#include "lldb/Expression/IRMemoryMap.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/StackFrame.h" + +#include <vector> + +namespace lldb_private +{ + +class Materializer +{ +public: + Materializer (); + ~Materializer (); + + class Dematerializer + { + public: + Dematerializer () : + m_materializer(NULL), + m_map(NULL), + m_process_address(LLDB_INVALID_ADDRESS) + { + } + + ~Dematerializer () + { + Wipe (); + } + + void Dematerialize (Error &err, + lldb::ClangExpressionVariableSP &result_sp, + lldb::addr_t frame_top, + lldb::addr_t frame_bottom); + + void Wipe (); + + bool IsValid () + { + return m_materializer && m_map && (m_process_address != LLDB_INVALID_ADDRESS); + } + private: + friend class Materializer; + + Dematerializer (Materializer &materializer, + lldb::StackFrameSP &frame_sp, + IRMemoryMap &map, + lldb::addr_t process_address) : + m_materializer(&materializer), + m_map(&map), + m_process_address(process_address) + { + if (frame_sp) + { + m_thread_wp = frame_sp->GetThread(); + m_stack_id = frame_sp->GetStackID(); + } + } + + Materializer *m_materializer; + lldb::ThreadWP m_thread_wp; + StackID m_stack_id; + IRMemoryMap *m_map; + lldb::addr_t m_process_address; + }; + + typedef std::shared_ptr<Dematerializer> DematerializerSP; + typedef std::weak_ptr<Dematerializer> DematerializerWP; + + DematerializerSP Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err); + + uint32_t AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err); + uint32_t AddVariable (lldb::VariableSP &variable_sp, Error &err); + uint32_t AddResultVariable (const TypeFromUser &type, bool is_lvalue, bool keep_in_memory, Error &err); + uint32_t AddSymbol (const Symbol &symbol_sp, Error &err); + uint32_t AddRegister (const RegisterInfo ®ister_info, Error &err); + + uint32_t GetStructAlignment () + { + return m_struct_alignment; + } + + uint32_t GetStructByteSize () + { + return m_current_offset; + } + + uint32_t GetResultOffset () + { + if (m_result_entity) + return m_result_entity->GetOffset(); + else + return UINT32_MAX; + } + + class Entity + { + public: + Entity () : + m_alignment(1), + m_size(0), + m_offset(0) + { + } + + virtual ~Entity () + { + } + + virtual void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) = 0; + virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, + lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err) = 0; + virtual void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) = 0; + virtual void Wipe (IRMemoryMap &map, lldb::addr_t process_address) = 0; + + uint32_t GetAlignment () + { + return m_alignment; + } + + uint32_t GetSize () + { + return m_size; + } + + uint32_t GetOffset () + { + return m_offset; + } + + void SetOffset (uint32_t offset) + { + m_offset = offset; + } + protected: + void SetSizeAndAlignmentFromType (ClangASTType &type); + + uint32_t m_alignment; + uint32_t m_size; + uint32_t m_offset; + }; + +private: + uint32_t AddStructMember (Entity &entity); + + typedef std::unique_ptr<Entity> EntityUP; + typedef std::vector<EntityUP> EntityVector; + + DematerializerWP m_dematerializer_wp; + EntityVector m_entities; + Entity *m_result_entity; + uint32_t m_current_offset; + uint32_t m_struct_alignment; +}; + +} + +#endif diff --git a/include/lldb/Host/Condition.h b/include/lldb/Host/Condition.h new file mode 100644 index 0000000..98439ee --- /dev/null +++ b/include/lldb/Host/Condition.h @@ -0,0 +1,124 @@ +//===-- Condition.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_DBCondition_h_ +#define liblldb_DBCondition_h_ +#if defined(__cplusplus) + + +#include <pthread.h> +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class TimeValue; + +//---------------------------------------------------------------------- +/// @class Condition Condition.h "lldb/Host/Condition.h" +/// @brief A C++ wrapper class for pthread condition variables. +/// +/// A class that wraps up a pthread condition (pthread_cond_t). The +/// class will create a pthread condition when an instance is +/// constructed, and detroy it when it is destructed. It also provides +/// access to the standard pthread condition calls. +//---------------------------------------------------------------------- +class Condition +{ +public: + + //------------------------------------------------------------------ + /// Default constructor + /// + /// The default constructor will initialize a new pthread condition + /// and maintain the condition in the object state. + //------------------------------------------------------------------ + Condition (); + + //------------------------------------------------------------------ + /// Destructor + /// + /// Destroys the pthread condition that the object owns. + //------------------------------------------------------------------ + ~Condition (); + + //------------------------------------------------------------------ + /// Unblock all threads waiting for a condition variable + /// + /// @return + /// The return value from \c pthread_cond_broadcast() + //------------------------------------------------------------------ + int + Broadcast (); + + //------------------------------------------------------------------ + /// Unblocks one thread waiting for the condition variable + /// + /// @return + /// The return value from \c pthread_cond_signal() + //------------------------------------------------------------------ + int + Signal (); + + //------------------------------------------------------------------ + /// Wait for the condition variable to be signaled. + /// + /// The Wait() function atomically blocks the current thread + /// waiting on this object's condition variable, and unblocks + /// \a mutex. The waiting thread unblocks only after another thread + /// signals or broadcasts this object's condition variable. + /// + /// If \a abstime is non-NULL, this function will return when the + /// system time reaches the time specified in \a abstime if the + /// condition variable doesn't get unblocked. If \a abstime is NULL + /// this function will wait for an infinite amount of time for the + /// condition variable to be unblocked. + /// + /// The current thread re-acquires the lock on \a mutex following + /// the wait. + /// + /// @param[in] mutex + /// The mutex to use in the \c pthread_cond_timedwait() or + /// \c pthread_cond_wait() calls. + /// + /// @param[in] abstime + /// An absolute time at which to stop waiting if non-NULL, else + /// wait an infinite amount of time for the condition variable + /// toget signaled. + /// + /// @param[out] timed_out + /// If not NULL, will be set to true if the wait timed out, and + // false otherwise. + /// + /// @see Condition::Broadcast() + /// @see Condition::Signal() + //------------------------------------------------------------------ + int + Wait (Mutex &mutex, const TimeValue *abstime = NULL, bool *timed_out = NULL); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + pthread_cond_t m_condition; ///< The condition variable. + + //------------------------------------------------------------------ + /// Get accessor to the pthread condition object. + /// + /// @return + /// A pointer to the condition variable owned by this object. + //------------------------------------------------------------------ + pthread_cond_t * + GetCondition (); +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif + diff --git a/include/lldb/Host/Config.h b/include/lldb/Host/Config.h new file mode 100644 index 0000000..2d5d39b --- /dev/null +++ b/include/lldb/Host/Config.h @@ -0,0 +1,35 @@ +//===-- Config.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_Config_h_ +#define liblldb_Config_h_ + +#if defined(__APPLE__) + +#include "lldb/Host/macosx/Config.h" + +#elif defined(__linux__) + +#include "lldb/Host/linux/Config.h" + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) + +#include "lldb/Host/freebsd/Config.h" + +#elif defined(__MINGW__) || defined (__MINGW32__) + +#include "lldb/Host/mingw/Config.h" + +#else + +#error undefined platform + +#endif + +#endif // #ifndef liblldb_Config_h_ diff --git a/include/lldb/Host/DynamicLibrary.h b/include/lldb/Host/DynamicLibrary.h new file mode 100644 index 0000000..1fcc7d1 --- /dev/null +++ b/include/lldb/Host/DynamicLibrary.h @@ -0,0 +1,51 @@ +//===-- DynamicLibrary.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_DynamicLibrary_h_ +#define liblldb_DynamicLibrary_h_ + +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" + +namespace lldb_private { + +class DynamicLibrary +{ +public: + DynamicLibrary (const FileSpec& spec, uint32_t options = Host::eDynamicLibraryOpenOptionLazy | + Host::eDynamicLibraryOpenOptionLocal | + Host::eDynamicLibraryOpenOptionLimitGetSymbol); + + ~DynamicLibrary (); + + template <typename T = void*> + T GetSymbol (const char* name) + { + Error err; + if (!m_handle) + return (T)NULL; + void* symbol = Host::DynamicLibraryGetSymbol (m_handle, name, err); + if (!symbol) + return (T)NULL; + return (T)symbol; + } + + bool + IsValid (); + +private: + lldb_private::FileSpec m_filespec; + void* m_handle; + + DISALLOW_COPY_AND_ASSIGN (DynamicLibrary); +}; + +} // namespace lldb_private + +#endif // liblldb_DynamicLibrary_h_ diff --git a/include/lldb/Host/Endian.h b/include/lldb/Host/Endian.h new file mode 100644 index 0000000..610f3ce --- /dev/null +++ b/include/lldb/Host/Endian.h @@ -0,0 +1,33 @@ +//===-- Endian.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_host_endian_h_ +#define liblldb_host_endian_h_ + +#include "lldb/lldb-enumerations.h" + +namespace lldb { + +namespace endian { + + static union EndianTest + { + uint32_t num; + uint8_t bytes[sizeof(uint32_t)]; + } const endianTest = { (uint16_t)0x01020304 }; + + inline ByteOrder InlHostByteOrder() { return (ByteOrder)endianTest.bytes[0]; } + +// ByteOrder const InlHostByteOrder = (ByteOrder)endianTest.bytes[0]; +} + +} + +#endif // liblldb_host_endian_h_ + diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h new file mode 100644 index 0000000..df7fe92 --- /dev/null +++ b/include/lldb/Host/File.h @@ -0,0 +1,500 @@ +//===-- File.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_File_h_ +#define liblldb_File_h_ +#if defined(__cplusplus) + +#include <stdio.h> + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class File File.h "lldb/Host/File.h" +/// @brief A file class. +/// +/// A file class that divides abstracts the LLDB core from host file +/// functionality. +//---------------------------------------------------------------------- +class File +{ +public: + static int kInvalidDescriptor; + static FILE * kInvalidStream; + + enum OpenOptions + { + eOpenOptionRead = (1u << 0), // Open file for reading + eOpenOptionWrite = (1u << 1), // Open file for writing + eOpenOptionAppend = (1u << 2), // Don't truncate file when opening, append to end of file + eOpenOptionTruncate = (1u << 3), // Truncate file when opening + eOpenOptionNonBlocking = (1u << 4), // File reads + eOpenOptionCanCreate = (1u << 5), // Create file if doesn't already exist + eOpenOptionCanCreateNewOnly = (1u << 6) // Can create file only if it doesn't already exist + }; + + enum Permissions + { + ePermissionsUserRead = (1u << 0), + ePermissionsUserWrite = (1u << 1), + ePermissionsUserExecute = (1u << 2), + ePermissionsGroupRead = (1u << 3), + ePermissionsGroupWrite = (1u << 4), + ePermissionsGroupExecute = (1u << 5), + ePermissionsWorldRead = (1u << 6), + ePermissionsWorldWrite = (1u << 7), + ePermissionsWorldExecute = (1u << 8), + + ePermissionsUserRW = (ePermissionsUserRead | ePermissionsUserWrite | 0 ), + ePermissionsUserRX = (ePermissionsUserRead | 0 | ePermissionsUserExecute ), + ePermissionsUserRWX = (ePermissionsUserRead | ePermissionsUserWrite | ePermissionsUserExecute ), + + ePermissionsGroupRW = (ePermissionsGroupRead | ePermissionsGroupWrite | 0 ), + ePermissionsGroupRX = (ePermissionsGroupRead | 0 | ePermissionsGroupExecute ), + ePermissionsGroupRWX = (ePermissionsGroupRead | ePermissionsGroupWrite | ePermissionsGroupExecute ), + + ePermissionsWorldRW = (ePermissionsWorldRead | ePermissionsWorldWrite | 0 ), + ePermissionsWorldRX = (ePermissionsWorldRead | 0 | ePermissionsWorldExecute ), + ePermissionsWorldRWX = (ePermissionsWorldRead | ePermissionsWorldWrite | ePermissionsWorldExecute ), + + ePermissionsEveryoneR = (ePermissionsUserRead | ePermissionsGroupRead | ePermissionsWorldRead ), + ePermissionsEveryoneW = (ePermissionsUserWrite | ePermissionsGroupWrite | ePermissionsWorldWrite ), + ePermissionsEveryoneX = (ePermissionsUserExecute | ePermissionsGroupExecute | ePermissionsWorldExecute ), + + ePermissionsEveryoneRW = (ePermissionsEveryoneR | ePermissionsEveryoneW | 0 ), + ePermissionsEveryoneRX = (ePermissionsEveryoneR | 0 | ePermissionsEveryoneX ), + ePermissionsEveryoneRWX = (ePermissionsEveryoneR | ePermissionsEveryoneW | ePermissionsEveryoneX ), + ePermissionsDefault = (ePermissionsUserRW | ePermissionsGroupRead) + }; + + File() : + m_descriptor (kInvalidDescriptor), + m_stream (kInvalidStream), + m_options (0), + m_owned (false) + { + } + + File (FILE *fh, bool transfer_ownership) : + m_descriptor (kInvalidDescriptor), + m_stream (fh), + m_options (0), + m_owned (transfer_ownership) + { + } + + File (const File &rhs); + + File & + operator= (const File &rhs); + //------------------------------------------------------------------ + /// Constructor with path. + /// + /// Takes a path to a file which can be just a filename, or a full + /// path. If \a path is not NULL or empty, this function will call + /// File::Open (const char *path, uint32_t options, uint32_t permissions). + /// + /// @param[in] path + /// The full or partial path to a file. + /// + /// @param[in] options + /// Options to use when opening (see File::OpenOptions) + /// + /// @param[in] permissions + /// Options to use when opening (see File::Permissions) + /// + /// @see File::Open (const char *path, uint32_t options, uint32_t permissions) + //------------------------------------------------------------------ + File (const char *path, + uint32_t options, + uint32_t permissions = ePermissionsDefault); + + + File (int fd, bool tranfer_ownership) : + m_descriptor (fd), + m_stream (kInvalidStream), + m_options (0), + m_owned (tranfer_ownership) + { + } + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual in case this class is subclassed. + //------------------------------------------------------------------ + virtual + ~File (); + + bool + IsValid () const + { + return DescriptorIsValid() || StreamIsValid(); + } + + //------------------------------------------------------------------ + /// Convert to pointer operator. + /// + /// This allows code to check a File object to see if it + /// contains anything valid using code such as: + /// + /// @code + /// File file(...); + /// if (file) + /// { ... + /// @endcode + /// + /// @return + /// A pointer to this object if either the directory or filename + /// is valid, NULL otherwise. + //------------------------------------------------------------------ + operator + bool () const + { + return DescriptorIsValid() || StreamIsValid(); + } + + //------------------------------------------------------------------ + /// Logical NOT operator. + /// + /// This allows code to check a File object to see if it is + /// invalid using code such as: + /// + /// @code + /// File file(...); + /// if (!file) + /// { ... + /// @endcode + /// + /// @return + /// Returns \b true if the object has an empty directory and + /// filename, \b false otherwise. + //------------------------------------------------------------------ + bool + operator! () const + { + return !DescriptorIsValid() && !StreamIsValid(); + } + + //------------------------------------------------------------------ + /// Get the file spec for this file. + /// + /// @return + /// A reference to the file specification object. + //------------------------------------------------------------------ + Error + GetFileSpec (FileSpec &file_spec) const; + + //------------------------------------------------------------------ + /// Open a file for read/writing with the specified options. + /// + /// Takes a path to a file which can be just a filename, or a full + /// path. + /// + /// @param[in] path + /// The full or partial path to a file. + /// + /// @param[in] options + /// Options to use when opening (see File::OpenOptions) + /// + /// @param[in] permissions + /// Options to use when opening (see File::Permissions) + //------------------------------------------------------------------ + Error + Open (const char *path, + uint32_t options, + uint32_t permissions = ePermissionsDefault); + + Error + Close (); + + Error + Duplicate (const File &rhs); + + int + GetDescriptor() const; + + void + SetDescriptor(int fd, bool transfer_ownership); + + FILE * + GetStream (); + + void + SetStream (FILE *fh, bool transfer_ownership); + + //------------------------------------------------------------------ + /// Read bytes from a file from the current file position. + /// + /// NOTE: This function is NOT thread safe. Use the read function + /// that takes an "off_t &offset" to ensure correct operation in + /// multi-threaded environments. + /// + /// @param[in] buf + /// A buffer where to put the bytes that are read. + /// + /// @param[in/out] num_bytes + /// The number of bytes to read form the current file position + /// which gets modified with the number of bytes that were read. + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Read (void *buf, size_t &num_bytes); + + //------------------------------------------------------------------ + /// Write bytes to a file at the current file position. + /// + /// NOTE: This function is NOT thread safe. Use the write function + /// that takes an "off_t &offset" to ensure correct operation in + /// multi-threaded environments. + /// + /// @param[in] buf + /// A buffer where to put the bytes that are read. + /// + /// @param[in/out] num_bytes + /// The number of bytes to write to the current file position + /// which gets modified with the number of bytes that were + /// written. + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Write (const void *buf, size_t &num_bytes); + + //------------------------------------------------------------------ + /// Seek to an offset relative to the beginning of the file. + /// + /// NOTE: This function is NOT thread safe, other threads that + /// access this object might also change the current file position. + /// For thread safe reads and writes see the following functions: + /// @see File::Read (void *, size_t, off_t &) + /// @see File::Write (const void *, size_t, off_t &) + /// + /// @param[in] offset + /// The offset to seek to within the file relative to the + /// beginning of the file. + /// + /// @param[in] error_ptr + /// A pointer to a lldb_private::Error object that will be + /// filled in if non-NULL. + /// + /// @return + /// The resulting seek offset, or -1 on error. + //------------------------------------------------------------------ + off_t + SeekFromStart (off_t offset, Error *error_ptr = NULL); + + //------------------------------------------------------------------ + /// Seek to an offset relative to the current file position. + /// + /// NOTE: This function is NOT thread safe, other threads that + /// access this object might also change the current file position. + /// For thread safe reads and writes see the following functions: + /// @see File::Read (void *, size_t, off_t &) + /// @see File::Write (const void *, size_t, off_t &) + /// + /// @param[in] offset + /// The offset to seek to within the file relative to the + /// current file position. + /// + /// @param[in] error_ptr + /// A pointer to a lldb_private::Error object that will be + /// filled in if non-NULL. + /// + /// @return + /// The resulting seek offset, or -1 on error. + //------------------------------------------------------------------ + off_t + SeekFromCurrent (off_t offset, Error *error_ptr = NULL); + + //------------------------------------------------------------------ + /// Seek to an offset relative to the end of the file. + /// + /// NOTE: This function is NOT thread safe, other threads that + /// access this object might also change the current file position. + /// For thread safe reads and writes see the following functions: + /// @see File::Read (void *, size_t, off_t &) + /// @see File::Write (const void *, size_t, off_t &) + /// + /// @param[in/out] offset + /// The offset to seek to within the file relative to the + /// end of the file which gets filled in the the resulting + /// absolute file offset. + /// + /// @param[in] error_ptr + /// A pointer to a lldb_private::Error object that will be + /// filled in if non-NULL. + /// + /// @return + /// The resulting seek offset, or -1 on error. + //------------------------------------------------------------------ + off_t + SeekFromEnd (off_t offset, Error *error_ptr = NULL); + + //------------------------------------------------------------------ + /// Read bytes from a file from the specified file offset. + /// + /// NOTE: This function is thread safe in that clients manager their + /// own file position markers and reads on other threads won't mess + /// up the current read. + /// + /// @param[in] buf + /// A buffer where to put the bytes that are read. + /// + /// @param[in/out] num_bytes + /// The number of bytes to read form the current file position + /// which gets modified with the number of bytes that were read. + /// + /// @param[in/out] offset + /// The offset within the file from which to read \a num_bytes + /// bytes. This offset gets incremented by the number of bytes + /// that were read. + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Read (void *dst, size_t &num_bytes, off_t &offset); + + //------------------------------------------------------------------ + /// Read bytes from a file from the specified file offset. + /// + /// NOTE: This function is thread safe in that clients manager their + /// own file position markers and reads on other threads won't mess + /// up the current read. + /// + /// @param[in/out] num_bytes + /// The number of bytes to read form the current file position + /// which gets modified with the number of bytes that were read. + /// + /// @param[in/out] offset + /// The offset within the file from which to read \a num_bytes + /// bytes. This offset gets incremented by the number of bytes + /// that were read. + /// + /// @param[in] null_terminate + /// Ensure that the data that is read is terminated with a NULL + /// character so that the data can be used as a C string. + /// + /// @param[out] data_buffer_sp + /// A data buffer to create and fill in that will contain any + /// data that is read from the file. This buffer will be reset + /// if an error occurs. + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Read (size_t &num_bytes, + off_t &offset, + bool null_terminate, + lldb::DataBufferSP &data_buffer_sp); + + //------------------------------------------------------------------ + /// Write bytes to a file at the specified file offset. + /// + /// NOTE: This function is thread safe in that clients manager their + /// own file position markers, though clients will need to implement + /// their own locking externally to avoid multiple people writing + /// to the file at the same time. + /// + /// @param[in] buf + /// A buffer containing the bytes to write. + /// + /// @param[in/out] num_bytes + /// The number of bytes to write to the file at offset \a offset. + /// \a num_bytes gets modified with the number of bytes that + /// were read. + /// + /// @param[in/out] offset + /// The offset within the file at which to write \a num_bytes + /// bytes. This offset gets incremented by the number of bytes + /// that were written. + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Write (const void *src, size_t &num_bytes, off_t &offset); + + //------------------------------------------------------------------ + /// Flush the current stream + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Flush (); + + //------------------------------------------------------------------ + /// Sync to disk. + /// + /// @return + /// An error object that indicates success or the reason for + /// failure. + //------------------------------------------------------------------ + Error + Sync (); + + //------------------------------------------------------------------ + /// Output printf formatted output to the stream. + /// + /// Print some formatted output to the stream. + /// + /// @param[in] format + /// A printf style format string. + /// + /// @param[in] ... + /// Variable arguments that are needed for the printf style + /// format string \a format. + //------------------------------------------------------------------ + size_t + Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + size_t + PrintfVarArg(const char *format, va_list args); + +protected: + + + bool + DescriptorIsValid () const + { + return m_descriptor >= 0; + } + + bool + StreamIsValid () const + { + return m_stream != kInvalidStream; + } + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + int m_descriptor; + FILE *m_stream; + uint32_t m_options; + bool m_owned; +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_File_h_ diff --git a/include/lldb/Host/FileSpec.h b/include/lldb/Host/FileSpec.h new file mode 100644 index 0000000..c58be9e --- /dev/null +++ b/include/lldb/Host/FileSpec.h @@ -0,0 +1,692 @@ +//===-- FileSpec.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_FileSpec_h_ +#define liblldb_FileSpec_h_ +#if defined(__cplusplus) + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/STLUtils.h" +#include "lldb/Host/TimeValue.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class FileSpec FileSpec.h "lldb/Host/FileSpec.h" +/// @brief A file utility class. +/// +/// A file specification class that divides paths up into a directory +/// and basename. These string values of the paths are put into uniqued +/// string pools for fast comparisons and efficient memory usage. +/// +/// Another reason the paths are split into the directory and basename +/// is to allow efficient debugger searching. Often in a debugger the +/// user types in the basename of the file, for example setting a +/// breakpoint by file and line, or specifying a module (shared library) +/// to limit the scope in which to execute a command. The user rarely +/// types in a full path. When the paths are already split up, it makes +/// it easy for us to compare only the basenames of a lot of file +/// specifications without having to split up the file path each time +/// to get to the basename. +//---------------------------------------------------------------------- +class FileSpec +{ +public: + typedef enum FileType + { + eFileTypeInvalid = -1, + eFileTypeUnknown = 0, + eFileTypeDirectory, + eFileTypePipe, + eFileTypeRegular, + eFileTypeSocket, + eFileTypeSymbolicLink, + eFileTypeOther + } FileType; + + FileSpec(); + + //------------------------------------------------------------------ + /// Constructor with path. + /// + /// Takes a path to a file which can be just a filename, or a full + /// path. If \a path is not NULL or empty, this function will call + /// FileSpec::SetFile (const char *path, bool resolve). + /// + /// @param[in] path + /// The full or partial path to a file. + /// + /// @param[in] resolve_path + /// If \b true, then we resolve the path with realpath, + /// if \b false we trust the path is in canonical form already. + /// + /// @see FileSpec::SetFile (const char *path, bool resolve) + //------------------------------------------------------------------ + explicit FileSpec (const char *path, bool resolve_path); + + //------------------------------------------------------------------ + /// Copy constructor + /// + /// Makes a copy of the uniqued directory and filename strings from + /// \a rhs. + /// + /// @param[in] rhs + /// A const FileSpec object reference to copy. + //------------------------------------------------------------------ + FileSpec (const FileSpec& rhs); + + //------------------------------------------------------------------ + /// Copy constructor + /// + /// Makes a copy of the uniqued directory and filename strings from + /// \a rhs if it is not NULL. + /// + /// @param[in] rhs + /// A const FileSpec object pointer to copy if non-NULL. + //------------------------------------------------------------------ + FileSpec (const FileSpec* rhs); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~FileSpec (); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// Makes a copy of the uniqued directory and filename strings from + /// \a rhs. + /// + /// @param[in] rhs + /// A const FileSpec object reference to assign to this object. + /// + /// @return + /// A const reference to this object. + //------------------------------------------------------------------ + const FileSpec& + operator= (const FileSpec& rhs); + + //------------------------------------------------------------------ + /// Equal to operator + /// + /// Tests if this object is equal to \a rhs. + /// + /// @param[in] rhs + /// A const FileSpec object reference to compare this object + /// to. + /// + /// @return + /// \b true if this object is equal to \a rhs, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + operator== (const FileSpec& rhs) const; + + //------------------------------------------------------------------ + /// Not equal to operator + /// + /// Tests if this object is not equal to \a rhs. + /// + /// @param[in] rhs + /// A const FileSpec object reference to compare this object + /// to. + /// + /// @return + /// \b true if this object is equal to \a rhs, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + operator!= (const FileSpec& rhs) const; + + //------------------------------------------------------------------ + /// Less than to operator + /// + /// Tests if this object is less than \a rhs. + /// + /// @param[in] rhs + /// A const FileSpec object reference to compare this object + /// to. + /// + /// @return + /// \b true if this object is less than \a rhs, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + operator< (const FileSpec& rhs) const; + + //------------------------------------------------------------------ + /// Convert to pointer operator. + /// + /// This allows code to check a FileSpec object to see if it + /// contains anything valid using code such as: + /// + /// @code + /// FileSpec file_spec(...); + /// if (file_spec) + /// { ... + /// @endcode + /// + /// @return + /// A pointer to this object if either the directory or filename + /// is valid, NULL otherwise. + //------------------------------------------------------------------ + operator bool() const; + + //------------------------------------------------------------------ + /// Logical NOT operator. + /// + /// This allows code to check a FileSpec object to see if it is + /// invalid using code such as: + /// + /// @code + /// FileSpec file_spec(...); + /// if (!file_spec) + /// { ... + /// @endcode + /// + /// @return + /// Returns \b true if the object has an empty directory and + /// filename, \b false otherwise. + //------------------------------------------------------------------ + bool + operator! () const; + + //------------------------------------------------------------------ + /// Clears the object state. + /// + /// Clear this object by releasing both the directory and filename + /// string values and reverting them to empty strings. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Compare two FileSpec objects. + /// + /// If \a full is true, then both the directory and the filename + /// must match. If \a full is false, then the directory names for + /// \a lhs and \a rhs are only compared if they are both not empty. + /// This allows a FileSpec object to only contain a filename + /// and it can match FileSpec objects that have matching + /// filenames with different paths. + /// + /// @param[in] lhs + /// A const reference to the Left Hand Side object to compare. + /// + /// @param[in] rhs + /// A const reference to the Right Hand Side object to compare. + /// + /// @param[in] full + /// If true, then both the directory and filenames will have to + /// match for a compare to return zero (equal to). If false + /// and either directory from \a lhs or \a rhs is empty, then + /// only the filename will be compared, else a full comparison + /// is done. + /// + /// @return + /// @li -1 if \a lhs is less than \a rhs + /// @li 0 if \a lhs is equal to \a rhs + /// @li 1 if \a lhs is greater than \a rhs + //------------------------------------------------------------------ + static int + Compare (const FileSpec& lhs, const FileSpec& rhs, bool full); + + static bool + Equal (const FileSpec& a, const FileSpec& b, bool full); + + //------------------------------------------------------------------ + /// Dump this object to a Stream. + /// + /// Dump the object to the supplied stream \a s. If the object + /// contains a valid directory name, it will be displayed followed + /// by a directory delimiter, and the filename. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s) const; + + //------------------------------------------------------------------ + /// Existence test. + /// + /// @return + /// \b true if the file exists on disk, \b false otherwise. + //------------------------------------------------------------------ + bool + Exists () const; + + + //------------------------------------------------------------------ + /// Expanded existence test. + /// + /// Call into the Host to see if it can help find the file (e.g. by + /// searching paths set in the environment, etc.). + /// + /// If found, sets the value of m_directory to the directory where + /// the file was found. + /// + /// @return + /// \b true if was able to find the file using expanded search + /// methods, \b false otherwise. + //------------------------------------------------------------------ + bool + ResolveExecutableLocation (); + + //------------------------------------------------------------------ + /// Canonicalize this file path (basically running the static + /// FileSpec::Resolve method on it). Useful if you asked us not to + /// resolve the file path when you set the file. + //------------------------------------------------------------------ + bool + ResolvePath (); + + uint64_t + GetByteSize() const; + + //------------------------------------------------------------------ + /// Directory string get accessor. + /// + /// @return + /// A reference to the directory string object. + //------------------------------------------------------------------ + ConstString & + GetDirectory (); + + //------------------------------------------------------------------ + /// Directory string const get accessor. + /// + /// @return + /// A const reference to the directory string object. + //------------------------------------------------------------------ + const ConstString & + GetDirectory () const; + + //------------------------------------------------------------------ + /// Filename string get accessor. + /// + /// @return + /// A reference to the filename string object. + //------------------------------------------------------------------ + ConstString & + GetFilename (); + + //------------------------------------------------------------------ + /// Filename string const get accessor. + /// + /// @return + /// A const reference to the filename string object. + //------------------------------------------------------------------ + const ConstString & + GetFilename () const; + + //------------------------------------------------------------------ + /// Returns true if the filespec represents an implementation source + /// file (files with a ".c", ".cpp", ".m", ".mm" (many more) + /// extension). + /// + /// @return + /// \b true if the filespec represents an implementation source + /// file, \b false otherwise. + //------------------------------------------------------------------ + bool + IsSourceImplementationFile () const; + + //------------------------------------------------------------------ + /// Returns true if the filespec represents path that is relative + /// path to the current working directory. + /// + /// @return + /// \b true if the filespec represents a current working + /// directory relative path, \b false otherwise. + //------------------------------------------------------------------ + bool + IsRelativeToCurrentWorkingDirectory () const; + + TimeValue + GetModificationTime () const; + + //------------------------------------------------------------------ + /// Extract the full path to the file. + /// + /// Extract the directory and path into a fixed buffer. This is + /// needed as the directory and path are stored in separate string + /// values. + /// + /// @param[out] path + /// The buffer in which to place the extracted full path. + /// + /// @param[in] max_path_length + /// The maximum length of \a path. + /// + /// @return + /// Returns the number of characters that would be needed to + /// properly copy the full path into \a path. If the returned + /// number is less than \a max_path_length, then the path is + /// properly copied and terminated. If the return value is + /// >= \a max_path_length, then the path was truncated (but is + /// still NULL terminated). + //------------------------------------------------------------------ + size_t + GetPath (char *path, size_t max_path_length) const; + + //------------------------------------------------------------------ + /// Extract the full path to the file. + /// + /// Extract the directory and path into a std::string, which is returned. + /// + /// @return + /// Returns a std::string with the directory and filename + /// concatenated. + //------------------------------------------------------------------ + std::string + GetPath () const; + + //------------------------------------------------------------------ + /// Extract the extension of the file. + /// + /// Returns a ConstString that represents the extension of the filename + /// for this FileSpec object. If this object does not represent a file, + /// or the filename has no extension, ConstString(NULL) is returned. + /// The dot ('.') character is not returned as part of the extension + /// + /// @return + /// Returns the extension of the file as a ConstString object. + //------------------------------------------------------------------ + ConstString + GetFileNameExtension () const; + + //------------------------------------------------------------------ + /// Return the filename without the extension part + /// + /// Returns a ConstString that represents the filename of this object + /// without the extension part (e.g. for a file named "foo.bar", "foo" + /// is returned) + /// + /// @return + /// Returns the filename without extension + /// as a ConstString object. + //------------------------------------------------------------------ + ConstString + GetFileNameStrippingExtension () const; + + FileType + GetFileType () const; + + bool + IsDirectory () const + { + return GetFileType() == FileSpec::eFileTypeDirectory; + } + + bool + IsPipe () const + { + return GetFileType() == FileSpec::eFileTypePipe; + } + + bool + IsRegularFile () const + { + return GetFileType() == FileSpec::eFileTypeRegular; + } + + bool + IsSocket () const + { + return GetFileType() == FileSpec::eFileTypeSocket; + } + + bool + IsSymbolicLink () const + { + return GetFileType() == FileSpec::eFileTypeSymbolicLink; + } + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// Return the size in bytes that this object takes in memory. This + /// returns the size in bytes of this object, not any shared string + /// values it may refer to. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + size_t + MemorySize () const; + + //------------------------------------------------------------------ + /// Memory map part of, or the entire contents of, a file. + /// + /// Returns a shared pointer to a data buffer that contains all or + /// part of the contents of a file. The data is memory mapped and + /// will lazily page in data from the file as memory is accessed. + /// The data that is mappped will start \a offset bytes into the + /// file, and \a length bytes will be mapped. If \a length is + /// greater than the number of bytes available in the file starting + /// at \a offset, the number of bytes will be appropriately + /// truncated. The final number of bytes that get mapped can be + /// verified using the DataBuffer::GetByteSize() function on the return + /// shared data pointer object contents. + /// + /// @param[in] offset + /// The offset in bytes from the beginning of the file where + /// memory mapping should begin. + /// + /// @param[in] length + /// The size in bytes that should be mapped starting \a offset + /// bytes into the file. If \a length is \c SIZE_MAX, map + /// as many bytes as possible. + /// + /// @return + /// A shared pointer to the memeory mapped data. This shared + /// pointer can contain a NULL DataBuffer pointer, so the contained + /// pointer must be checked prior to using it. + //------------------------------------------------------------------ + lldb::DataBufferSP + MemoryMapFileContents (off_t offset = 0, size_t length = SIZE_MAX) const; + + //------------------------------------------------------------------ + /// Read part of, or the entire contents of, a file into a heap based data buffer. + /// + /// Returns a shared pointer to a data buffer that contains all or + /// part of the contents of a file. The data copies into a heap based + /// buffer that lives in the DataBuffer shared pointer object returned. + /// The data that is cached will start \a offset bytes into the + /// file, and \a length bytes will be mapped. If \a length is + /// greater than the number of bytes available in the file starting + /// at \a offset, the number of bytes will be appropriately + /// truncated. The final number of bytes that get mapped can be + /// verified using the DataBuffer::GetByteSize() function. + /// + /// @param[in] offset + /// The offset in bytes from the beginning of the file where + /// memory mapping should begin. + /// + /// @param[in] length + /// The size in bytes that should be mapped starting \a offset + /// bytes into the file. If \a length is \c SIZE_MAX, map + /// as many bytes as possible. + /// + /// @return + /// A shared pointer to the memeory mapped data. This shared + /// pointer can contain a NULL DataBuffer pointer, so the contained + /// pointer must be checked prior to using it. + //------------------------------------------------------------------ + lldb::DataBufferSP + ReadFileContents (off_t offset = 0, size_t length = SIZE_MAX, Error *error_ptr = NULL) const; + + size_t + ReadFileContents (off_t file_offset, void *dst, size_t dst_len, Error *error_ptr) const; + + + //------------------------------------------------------------------ + /// Read the entire contents of a file as data that can be used + /// as a C string. + /// + /// Read the entire contents of a file and ensure that the data + /// is NULL terminated so it can be used as a C string. + /// + /// @return + /// A shared pointer to the data. This shared pointer can + /// contain a NULL DataBuffer pointer, so the contained pointer + /// must be checked prior to using it. + //------------------------------------------------------------------ + lldb::DataBufferSP + ReadFileContentsAsCString(Error *error_ptr = NULL); + //------------------------------------------------------------------ + /// Change the file specificed with a new path. + /// + /// Update the contents of this object with a new path. The path will + /// be split up into a directory and filename and stored as uniqued + /// string values for quick comparison and efficient memory usage. + /// + /// @param[in] path + /// A full, partial, or relative path to a file. + /// + /// @param[in] resolve_path + /// If \b true, then we will try to resolve links the path using + /// the static FileSpec::Resolve. + //------------------------------------------------------------------ + void + SetFile (const char *path, bool resolve_path); + + bool + IsResolved () const + { + return m_is_resolved; + } + + //------------------------------------------------------------------ + /// Set if the file path has been resolved or not. + /// + /// If you know a file path is already resolved and avoided passing + /// a \b true parameter for any functions that take a "bool + /// resolve_path" parameter, you can set the value manually using + /// this call to make sure we don't try and resolve it later, or try + /// and resolve a path that has already been resolved. + /// + /// @param[in] is_resolved + /// A boolean value that will replace the current value that + /// indicates if the paths in this object have been resolved. + //------------------------------------------------------------------ + void + SetIsResolved (bool is_resolved) + { + m_is_resolved = is_resolved; + } + //------------------------------------------------------------------ + /// Read the file into an array of strings, one per line. + /// + /// Opens and reads the file in this object into an array of strings, + /// one string per line of the file. Returns a boolean indicating + /// success or failure. + /// + /// @param[out] lines + /// The string array into which to read the file. + /// + /// @result + /// Returns the number of lines that were read from the file. + //------------------------------------------------------------------ + size_t + ReadFileLines (STLStringArray &lines); + + //------------------------------------------------------------------ + /// Resolves user name and links in \a src_path, and writes the output + /// to \a dst_path. Note if the path pointed to by \a src_path does not + /// exist, the contents of \a src_path will be copied to \a dst_path + /// unchanged. + /// + /// @param[in] src_path + /// Input path to be resolved. + /// + /// @param[in] dst_path + /// Buffer to store the resolved path. + /// + /// @param[in] dst_len + /// Size of the buffer pointed to by dst_path. + /// + /// @result + /// The number of characters required to write the resolved path. If the + /// resolved path doesn't fit in dst_len, dst_len-1 characters will + /// be written to \a dst_path, but the actual required length will still be returned. + //------------------------------------------------------------------ + static size_t + Resolve (const char *src_path, char *dst_path, size_t dst_len); + + //------------------------------------------------------------------ + /// Resolves the user name at the beginning of \a src_path, and writes the output + /// to \a dst_path. Note, \a src_path can contain other path components after the + /// user name, they will be copied over, and if the path doesn't start with "~" it + /// will also be copied over to \a dst_path. + /// + /// @param[in] src_path + /// Input path to be resolved. + /// + /// @param[in] dst_path + /// Buffer to store the resolved path. + /// + /// @param[in] dst_len + /// Size of the buffer pointed to by dst_path. + /// + /// @result + /// The number of characters required to write the resolved path, or 0 if + /// the user name could not be found. If the + /// resolved path doesn't fit in dst_len, dst_len-1 characters will + /// be written to \a dst_path, but the actual required length will still be returned. + //------------------------------------------------------------------ + static size_t + ResolveUsername (const char *src_path, char *dst_path, size_t dst_len); + + static size_t + ResolvePartialUsername (const char *partial_name, StringList &matches); + + enum EnumerateDirectoryResult + { + eEnumerateDirectoryResultNext, // Enumerate next entry in the current directory + eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a directory or symlink, or next if not + eEnumerateDirectoryResultExit, // Exit from the current directory at the current level. + eEnumerateDirectoryResultQuit // Stop directory enumerations at any level + }; + + typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType) (void *baton, + FileType file_type, + const FileSpec &spec +); + + static EnumerateDirectoryResult + EnumerateDirectory (const char *dir_path, + bool find_directories, + bool find_files, + bool find_other, + EnumerateDirectoryCallbackType callback, + void *callback_baton); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + ConstString m_directory; ///< The uniqued directory path + ConstString m_filename; ///< The uniqued filename path + mutable bool m_is_resolved; ///< True if this path has been resolved. +}; + +//---------------------------------------------------------------------- +/// Dump a FileSpec object to a stream +//---------------------------------------------------------------------- +Stream& operator << (Stream& s, const FileSpec& f); + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_FileSpec_h_ diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h new file mode 100644 index 0000000..547bdd5 --- /dev/null +++ b/include/lldb/Host/Host.h @@ -0,0 +1,502 @@ +//===-- Host.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_Host_h_ +#define liblldb_Host_h_ +#if defined(__cplusplus) + +#include <stdarg.h> + +#include <map> +#include <string> + +#include "lldb/lldb-private.h" +#include "lldb/Core/StringList.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Host Host.h "lldb/Host/Host.h" +/// @brief A class that provides host computer information. +/// +/// Host is a class that answers information about the host operating +/// system. +//---------------------------------------------------------------------- +class Host +{ +public: + typedef bool (*MonitorChildProcessCallback) (void *callback_baton, + lldb::pid_t pid, + bool exited, + int signal, // Zero for no signal + int status); // Exit value of process if signal is zero + + //------------------------------------------------------------------ + /// Start monitoring a child process. + /// + /// Allows easy monitoring of child processes. \a callback will be + /// called when the child process exits or if it gets a signal. The + /// callback will only be called with signals if \a monitor_signals + /// is \b true. \a callback will usually be called from another + /// thread so the callback function must be thread safe. + /// + /// When the callback gets called, the return value indicates if + /// minotoring should stop. If \b true is returned from \a callback + /// the information will be removed. If \b false is returned then + /// monitoring will continue. If the child process exits, the + /// monitoring will automatically stop after the callback returned + /// ragardless of the callback return value. + /// + /// @param[in] callback + /// A function callback to call when a child receives a signal + /// (if \a monitor_signals is true) or a child exits. + /// + /// @param[in] callback_baton + /// A void * of user data that will be pass back when + /// \a callback is called. + /// + /// @param[in] pid + /// The process ID of a child process to monitor, -1 for all + /// processes. + /// + /// @param[in] monitor_signals + /// If \b true the callback will get called when the child + /// process gets a signal. If \b false, the callback will only + /// get called if the child process exits. + /// + /// @return + /// A thread handle that can be used to cancel the thread that + /// was spawned to monitor \a pid. + /// + /// @see static void Host::StopMonitoringChildProcess (uint32_t) + //------------------------------------------------------------------ + static lldb::thread_t + StartMonitoringChildProcess (MonitorChildProcessCallback callback, + void *callback_baton, + lldb::pid_t pid, + bool monitor_signals); + + //------------------------------------------------------------------ + /// Get the host page size. + /// + /// @return + /// The size in bytes of a VM page on the host system. + //------------------------------------------------------------------ + static size_t + GetPageSize(); + + //------------------------------------------------------------------ + /// Returns the endianness of the host system. + /// + /// @return + /// Returns the endianness of the host system as a lldb::ByteOrder + /// enumeration. + //------------------------------------------------------------------ + static lldb::ByteOrder + GetByteOrder (); + + //------------------------------------------------------------------ + /// Returns the number of CPUs on this current host. + /// + /// @return + /// Number of CPUs on this current host, or zero if the number + /// of CPUs can't be determined on this host. + //------------------------------------------------------------------ + static uint32_t + GetNumberCPUS (); + + static bool + GetOSVersion (uint32_t &major, + uint32_t &minor, + uint32_t &update); + + static bool + GetOSBuildString (std::string &s); + + static bool + GetOSKernelDescription (std::string &s); + + static bool + GetHostname (std::string &s); + + static const char * + GetUserName (uint32_t uid, std::string &user_name); + + static const char * + GetGroupName (uint32_t gid, std::string &group_name); + + static uint32_t + GetUserID (); + + static uint32_t + GetGroupID (); + + static uint32_t + GetEffectiveUserID (); + + static uint32_t + GetEffectiveGroupID (); + + + enum SystemLogType + { + eSystemLogWarning, + eSystemLogError + }; + + static void + SystemLog (SystemLogType type, const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + static void + SystemLog (SystemLogType type, const char *format, va_list args); + + //------------------------------------------------------------------ + /// Gets the host architecture. + /// + /// @return + /// A const architecture object that represents the host + /// architecture. + //------------------------------------------------------------------ + enum SystemDefaultArchitecture + { + eSystemDefaultArchitecture, // The overall default architecture that applications will run on this host + eSystemDefaultArchitecture32, // If this host supports 32 bit programs, return the default 32 bit arch + eSystemDefaultArchitecture64 // If this host supports 64 bit programs, return the default 64 bit arch + }; + + static const ArchSpec & + GetArchitecture (SystemDefaultArchitecture arch_kind = eSystemDefaultArchitecture); + + //------------------------------------------------------------------ + /// Gets the host vendor string. + /// + /// @return + /// A const string object containing the host vendor name. + //------------------------------------------------------------------ + static const ConstString & + GetVendorString (); + + //------------------------------------------------------------------ + /// Gets the host Operating System (OS) string. + /// + /// @return + /// A const string object containing the host OS name. + //------------------------------------------------------------------ + static const ConstString & + GetOSString (); + + //------------------------------------------------------------------ + /// Gets the host target triple as a const string. + /// + /// @return + /// A const string object containing the host target triple. + //------------------------------------------------------------------ + static const ConstString & + GetTargetTriple (); + + //------------------------------------------------------------------ + /// Get the process ID for the calling process. + /// + /// @return + /// The process ID for the current process. + //------------------------------------------------------------------ + static lldb::pid_t + GetCurrentProcessID (); + + //------------------------------------------------------------------ + /// Get the thread ID for the calling thread in the current process. + /// + /// @return + /// The thread ID for the calling thread in the current process. + //------------------------------------------------------------------ + static lldb::tid_t + GetCurrentThreadID (); + + //------------------------------------------------------------------ + /// Get the thread token (the one returned by ThreadCreate when the thread was created) for the + /// calling thread in the current process. + /// + /// @return + /// The thread token for the calling thread in the current process. + //------------------------------------------------------------------ + static lldb::thread_t + GetCurrentThread (); + + static const char * + GetSignalAsCString (int signo); + + static void + WillTerminate (); + //------------------------------------------------------------------ + /// Host specific thread created function call. + /// + /// This function call lets the current host OS do any thread + /// specific initialization that it needs, including naming the + /// thread. No cleanup routine is exptected to be called + /// + /// @param[in] name + /// The current thread's name in the current process. + //------------------------------------------------------------------ + static void + ThreadCreated (const char *name); + + static lldb::thread_t + ThreadCreate (const char *name, + lldb::thread_func_t function, + lldb::thread_arg_t thread_arg, + Error *err); + + static bool + ThreadCancel (lldb::thread_t thread, + Error *error); + + static bool + ThreadDetach (lldb::thread_t thread, + Error *error); + static bool + ThreadJoin (lldb::thread_t thread, + lldb::thread_result_t *thread_result_ptr, + Error *error); + + //------------------------------------------------------------------ + /// Gets the name of a thread in a process. + /// + /// This function will name a thread in a process using it's own + /// thread name pool, and also will attempt to set a thread name + /// using any supported host OS APIs. + /// + /// @param[in] pid + /// The process ID in which we are trying to get the name of + /// a thread. + /// + /// @param[in] tid + /// The thread ID for which we are trying retrieve the name of. + /// + /// @return + /// A std::string containing the thread name. + //------------------------------------------------------------------ + static std::string + GetThreadName (lldb::pid_t pid, lldb::tid_t tid); + + //------------------------------------------------------------------ + /// Sets the name of a thread in the current process. + /// + /// @param[in] pid + /// The process ID in which we are trying to name a thread. + /// + /// @param[in] tid + /// The thread ID which we are trying to name. + /// + /// @param[in] name + /// The current thread's name in the current process to \a name. + /// + /// @return + /// \b true if the thread name was able to be set, \b false + /// otherwise. + //------------------------------------------------------------------ + static bool + SetThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name); + + //------------------------------------------------------------------ + /// Sets a shortened name of a thread in the current process. + /// + /// @param[in] pid + /// The process ID in which we are trying to name a thread. + /// + /// @param[in] tid + /// The thread ID which we are trying to name. + /// + /// @param[in] name + /// The current thread's name in the current process to \a name. + /// + /// @param[in] len + /// The maximum length for the thread's shortened name. + /// + /// @return + /// \b true if the thread name was able to be set, \b false + /// otherwise. + static bool + SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name, size_t len); + + //------------------------------------------------------------------ + /// Gets the FileSpec of the current process (the process that + /// that is running the LLDB code). + /// + /// @return + /// \b A file spec with the program name. + //------------------------------------------------------------------ + static FileSpec + GetProgramFileSpec (); + + //------------------------------------------------------------------ + /// Given an address in the current process (the process that + /// is running the LLDB code), return the name of the module that + /// it comes from. This can be useful when you need to know the + /// path to the shared library that your code is running in for + /// loading resources that are relative to your binary. + /// + /// @param[in] host_addr + /// The pointer to some code in the current process. + /// + /// @return + /// \b A file spec with the module that contains \a host_addr, + /// which may be invalid if \a host_addr doesn't fall into + /// any valid module address range. + //------------------------------------------------------------------ + static FileSpec + GetModuleFileSpecForHostAddress (const void *host_addr); + + + + //------------------------------------------------------------------ + /// If you have an executable that is in a bundle and want to get + /// back to the bundle directory from the path itself, this + /// function will change a path to a file within a bundle to the + /// bundle directory itself. + /// + /// @param[in] file + /// A file spec that might point to a file in a bundle. + /// + /// @param[out] bundle_directory + /// An object will be filled in with the bundle directory for + /// the bundle when \b true is returned. Otherwise \a file is + /// left untouched and \b false is returned. + /// + /// @return + /// \b true if \a file was resolved in \a bundle_directory, + /// \b false otherwise. + //------------------------------------------------------------------ + static bool + GetBundleDirectory (const FileSpec &file, FileSpec &bundle_directory); + + //------------------------------------------------------------------ + /// When executable files may live within a directory, where the + /// directory represents an executable bundle (like the MacOSX + /// app bundles), the locate the executable within the containing + /// bundle. + /// + /// @param[in,out] file + /// A file spec that currently points to the bundle that will + /// be filled in with the executable path within the bundle + /// if \b true is returned. Otherwise \a file is left untouched. + /// + /// @return + /// \b true if \a file was resolved, \b false if this function + /// was not able to resolve the path. + //------------------------------------------------------------------ + static bool + ResolveExecutableInBundle (FileSpec &file); + + //------------------------------------------------------------------ + /// Find a resource files that are related to LLDB. + /// + /// Operating systems have different ways of storing shared + /// libraries and related resources. This function abstracts the + /// access to these paths. + /// + /// @param[in] path_type + /// The type of LLDB resource path you are looking for. If the + /// enumeration ends with "Dir", then only the \a file_spec's + /// directory member gets filled in. + /// + /// @param[in] file_spec + /// A file spec that gets filled in with the appriopriate path. + /// + /// @return + /// \b true if \a resource_path was resolved, \a false otherwise. + //------------------------------------------------------------------ + static bool + GetLLDBPath (PathType path_type, + FileSpec &file_spec); + + //------------------------------------------------------------------ + /// Set a string that can be displayed if host application crashes. + /// + /// Some operating systems have the ability to print a description + /// for shared libraries when a program crashes. If the host OS + /// supports such a mechanism, it should be implemented to help + /// with crash triage. + /// + /// @param[in] format + /// A printf format that will be used to form a new crash + /// description string. + //------------------------------------------------------------------ + static void + SetCrashDescriptionWithFormat (const char *format, ...) __attribute__ ((format (printf, 1, 2))); + + static void + SetCrashDescription (const char *description); + + static uint32_t + FindProcesses (const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &proc_infos); + + typedef std::map<lldb::pid_t, bool> TidMap; + typedef std::pair<lldb::pid_t, bool> TidPair; + static bool + FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach); + + static bool + GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info); + + static lldb::pid_t + LaunchApplication (const FileSpec &app_file_spec); + + static Error + LaunchProcess (ProcessLaunchInfo &launch_info); + + static Error + RunShellCommand (const char *command, // Shouldn't be NULL + const char *working_dir, // Pass NULL to use the current working directory + int *status_ptr, // Pass NULL if you don't want the process exit status + int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit + std::string *command_output, // Pass NULL if you don't want the command output + uint32_t timeout_sec, + const char *shell = "/bin/bash"); + + static lldb::DataBufferSP + GetAuxvData (lldb_private::Process *process); + + static lldb::TargetSP + GetDummyTarget (Debugger &debugger); + + static bool + OpenFileInExternalEditor (const FileSpec &file_spec, + uint32_t line_no); + + static void + Backtrace (Stream &strm, uint32_t max_frames); + + static size_t + GetEnvironment (StringList &env); + + enum DynamicLibraryOpenOptions + { + eDynamicLibraryOpenOptionLazy = (1u << 0), // Lazily resolve symbols in this dynamic library + eDynamicLibraryOpenOptionLocal = (1u << 1), // Only open a shared library with local access (hide it from the global symbol namespace) + eDynamicLibraryOpenOptionLimitGetSymbol = (1u << 2) // DynamicLibraryGetSymbol calls on this handle will only return matches from this shared library + }; + static void * + DynamicLibraryOpen (const FileSpec &file_spec, + uint32_t options, + Error &error); + + static Error + DynamicLibraryClose (void *dynamic_library_handle); + + static void * + DynamicLibraryGetSymbol (void *dynamic_library_handle, + const char *symbol_name, + Error &error); +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Host_h_ diff --git a/include/lldb/Host/Mutex.h b/include/lldb/Host/Mutex.h new file mode 100644 index 0000000..63f759e --- /dev/null +++ b/include/lldb/Host/Mutex.h @@ -0,0 +1,312 @@ +//===-- Mutex.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_Mutex_h_ +#define liblldb_Mutex_h_ +#if defined(__cplusplus) + +#include <pthread.h> +#include <assert.h> + +#ifdef LLDB_CONFIGURATION_DEBUG +#include <string> +#endif + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Mutex Mutex.h "lldb/Host/Mutex.h" +/// @brief A C++ wrapper class for pthread mutexes. +//---------------------------------------------------------------------- +class Mutex +{ +public: + friend class Locker; + friend class Condition; + + enum Type + { + eMutexTypeNormal, ///< Mutex that can't recursively entered by the same thread + eMutexTypeRecursive ///< Mutex can be recursively entered by the same thread + }; + + //------------------------------------------------------------------ + /// @class Mutex::Locker + /// + /// A scoped locking class that allows a variety of pthread mutex + /// objects to have a mutex locked when an Mutex::Locker + /// object is created, and unlocked when it goes out of scope or + /// when the Mutex::Locker::Reset(pthread_mutex_t *) + /// is called. This provides an exception safe way to lock a mutex + /// in a scope. + //------------------------------------------------------------------ + class Locker + { + public: + //-------------------------------------------------------------- + /// Default constructor. + /// + /// This will create a scoped mutex locking object that doesn't + /// have a mutex to lock. One will need to be provided using the + /// Mutex::Locker::Reset(pthread_mutex_t *) method. + /// + /// @see Mutex::Locker::Reset(pthread_mutex_t *) + //-------------------------------------------------------------- + Locker(); + + //-------------------------------------------------------------- + /// Constructor with a Mutex object. + /// + /// This will create a scoped mutex locking object that extracts + /// the mutex owned by \a m and locks it. + /// + /// @param[in] m + /// An instance of a Mutex object that contains a + /// valid mutex object. + //-------------------------------------------------------------- + Locker(Mutex& m); + + //-------------------------------------------------------------- + /// Constructor with a Mutex object pointer. + /// + /// This will create a scoped mutex locking object that extracts + /// the mutex owned by a m and locks it. + /// + /// @param[in] m + /// A pointer to instance of a Mutex object that + /// contains a valid mutex object. + //-------------------------------------------------------------- + Locker(Mutex* m); + + //-------------------------------------------------------------- + /// Desstructor + /// + /// Unlocks any valid pthread_mutex_t that this object may + /// contain. + //-------------------------------------------------------------- + ~Locker(); + + //-------------------------------------------------------------- + /// Change the contained mutex. + /// + /// Unlock the current mutex in this object (if it contains a + /// valid mutex) and lock the new \a mutex object if it is + /// non-NULL. + //-------------------------------------------------------------- + void + Lock (Mutex &mutex); + + void + Lock (Mutex *mutex) + { + if (mutex) + Lock(*mutex); + } + + //-------------------------------------------------------------- + /// Change the contained mutex only if the mutex can be locked. + /// + /// Unlock the current mutex in this object (if it contains a + /// valid mutex) and try to lock \a mutex. If \a mutex can be + /// locked this object will take ownership of the lock and will + /// unlock it when it goes out of scope or Reset or TryLock are + /// called again. If the mutex is already locked, this object + /// will not take ownership of the mutex. + /// + /// @return + /// Returns \b true if the lock was aquired and the this + /// object will unlock the mutex when it goes out of scope, + /// returns \b false otherwise. + //-------------------------------------------------------------- + bool + TryLock (Mutex &mutex, const char *failure_message = NULL); + + bool + TryLock (Mutex *mutex, const char *failure_message = NULL) + { + if (mutex) + return TryLock(*mutex, failure_message); + else + return false; + } + + void + Unlock (); + + protected: + //-------------------------------------------------------------- + /// Member variables + //-------------------------------------------------------------- + Mutex *m_mutex_ptr; + + private: + Locker(const Locker&); + const Locker& operator=(const Locker&); + }; + + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Creates a pthread mutex with no attributes. + //------------------------------------------------------------------ + Mutex(); + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Creates a pthread mutex with \a type as the mutex type. + /// Valid values for \a type include: + /// @li Mutex::Type::eMutexTypeNormal + /// @li Mutex::Type::eMutexTypeRecursive + /// + /// @param[in] type + /// The type of the mutex. + /// + /// @see ::pthread_mutexattr_settype() + //------------------------------------------------------------------ + Mutex(Mutex::Type type); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// Destroys the mutex owned by this object. + //------------------------------------------------------------------ +#ifdef LLDB_CONFIGURATION_DEBUG + virtual +#endif + ~Mutex(); + + //------------------------------------------------------------------ + /// Lock the mutex. + /// + /// Locks the mutex owned by this object. If the mutex is already + /// locked, the calling thread will block until the mutex becomes + /// available. + /// + /// @return + /// The error code from \c pthread_mutex_lock(). + //------------------------------------------------------------------ +#ifdef LLDB_CONFIGURATION_DEBUG + virtual +#endif + int + Lock(); + + //------------------------------------------------------------------ + /// Try to lock the mutex. + /// + /// Attempts to lock the mutex owned by this object without blocking. + /// If the mutex is already locked, TryLock() will not block waiting + /// for the mutex, but will return an error condition. + /// + /// @return + /// The error code from \c pthread_mutex_trylock(). + //------------------------------------------------------------------ +#ifdef LLDB_CONFIGURATION_DEBUG + virtual +#endif + int + TryLock(const char *failure_message = NULL); + + //------------------------------------------------------------------ + /// Unlock the mutex. + /// + /// If the current thread holds the lock on the owned mutex, then + /// Unlock() will unlock the mutex. Calling Unlock() on this object + /// when the calling thread does not hold the lock will result in + /// undefined behavior. + /// + /// @return + /// The error code from \c pthread_mutex_unlock(). + //------------------------------------------------------------------ +#ifdef LLDB_CONFIGURATION_DEBUG + virtual +#endif + int + Unlock(); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + // TODO: Hide the mutex in the implementation file in case we ever need to port to an + // architecture that doesn't have pthread mutexes. + pthread_mutex_t m_mutex; ///< The pthread mutex object. + +private: + //------------------------------------------------------------------ + /// Mutex get accessor. + /// + /// @return + /// A pointer to the pthread mutex object owned by this object. + //------------------------------------------------------------------ + pthread_mutex_t * + GetMutex(); + + Mutex(const Mutex&); + const Mutex& operator=(const Mutex&); +}; + +#ifdef LLDB_CONFIGURATION_DEBUG +class TrackingMutex : public Mutex +{ +public: + TrackingMutex() : Mutex() {} + TrackingMutex(Mutex::Type type) : Mutex (type) {} + + virtual + ~TrackingMutex() {} + + virtual int + Unlock (); + + virtual int + TryLock (const char *failure_message = NULL) + { + int return_value = Mutex::TryLock(); + if (return_value != 0 && failure_message != NULL) + { + m_failure_message.assign(failure_message); + m_thread_that_tried = pthread_self(); + } + return return_value; + } + +protected: + pthread_t m_thread_that_tried; + std::string m_failure_message; +}; + +class LoggingMutex : public Mutex +{ +public: + LoggingMutex() : Mutex(),m_locked(false) {} + LoggingMutex(Mutex::Type type) : Mutex (type),m_locked(false) {} + + virtual + ~LoggingMutex() {} + + virtual int + Lock (); + + virtual int + Unlock (); + + virtual int + TryLock (const char *failure_message = NULL); +protected: + bool m_locked; +}; +#endif + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif diff --git a/include/lldb/Host/Predicate.h b/include/lldb/Host/Predicate.h new file mode 100644 index 0000000..6ddf20b --- /dev/null +++ b/include/lldb/Host/Predicate.h @@ -0,0 +1,509 @@ +//===-- Predicate.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_Predicate_h_ +#define liblldb_Predicate_h_ +#if defined(__cplusplus) + +#include "lldb/Host/Mutex.h" +#include "lldb/Host/Condition.h" +#include <stdint.h> +#include <time.h> + +//#define DB_PTHREAD_LOG_EVENTS + +//---------------------------------------------------------------------- +/// Enumerations for broadcasting. +//---------------------------------------------------------------------- +namespace lldb_private { + +typedef enum +{ + eBroadcastNever, ///< No broadcast will be sent when the value is modified. + eBroadcastAlways, ///< Always send a broadcast when the value is modified. + eBroadcastOnChange ///< Only broadcast if the value changes when the value is modified. + +} PredicateBroadcastType; + +//---------------------------------------------------------------------- +/// @class Predicate Predicate.h "lldb/Host/Predicate.h" +/// @brief A C++ wrapper class for providing threaded access to a value +/// of type T. +/// +/// A templatized class that provides multi-threaded access to a value +/// of type T. Threads can efficiently wait for bits within T to be set +/// or reset, or wait for T to be set to be equal/not equal to a +/// specified values. +//---------------------------------------------------------------------- +template <class T> +class Predicate +{ +public: + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initializes the mutex, condition and value with their default + /// constructors. + //------------------------------------------------------------------ + Predicate () : + m_value(), + m_mutex(), + m_condition() + { + } + + //------------------------------------------------------------------ + /// Construct with initial T value \a initial_value. + /// + /// Initializes the mutex and condition with their default + /// constructors, and initializes the value with \a initial_value. + /// + /// @param[in] initial_value + /// The initial value for our T object. + //------------------------------------------------------------------ + Predicate (T initial_value) : + m_value(initial_value), + m_mutex(), + m_condition() + { + } + + //------------------------------------------------------------------ + /// Destructor. + /// + /// Destrory the condition, mutex, and T objects. + //------------------------------------------------------------------ + ~Predicate () + { + } + + + //------------------------------------------------------------------ + /// Value get accessor. + /// + /// Copies the current \a m_value in a thread safe manor and returns + /// the copied value. + /// + /// @return + /// A copy of the current value. + //------------------------------------------------------------------ + T + GetValue () const + { + Mutex::Locker locker(m_mutex); + T value = m_value; + return value; + } + + //------------------------------------------------------------------ + /// Value set accessor. + /// + /// Set the contained \a m_value to \a new_value in a thread safe + /// way and broadcast if needed. + /// + /// @param[in] value + /// The new value to set. + /// + /// @param[in] broadcast_type + /// A value indicating when and if to broadast. See the + /// PredicateBroadcastType enumeration for details. + /// + /// @see Predicate::Broadcast() + //------------------------------------------------------------------ + void + SetValue (T value, PredicateBroadcastType broadcast_type) + { + Mutex::Locker locker(m_mutex); +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (value = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, value, broadcast_type); +#endif + const T old_value = m_value; + m_value = value; + + Broadcast(old_value, broadcast_type); + } + + //------------------------------------------------------------------ + /// Set some bits in \a m_value. + /// + /// Logically set the bits \a bits in the contained \a m_value in a + /// thread safe way and broadcast if needed. + /// + /// @param[in] bits + /// The bits to set in \a m_value. + /// + /// @param[in] broadcast_type + /// A value indicating when and if to broadast. See the + /// PredicateBroadcastType enumeration for details. + /// + /// @see Predicate::Broadcast() + //------------------------------------------------------------------ + void + SetValueBits (T bits, PredicateBroadcastType broadcast_type) + { + Mutex::Locker locker(m_mutex); +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (bits = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, bits, broadcast_type); +#endif + const T old_value = m_value; + m_value |= bits; + + Broadcast(old_value, broadcast_type); + } + + //------------------------------------------------------------------ + /// Reset some bits in \a m_value. + /// + /// Logically reset (clear) the bits \a bits in the contained + /// \a m_value in a thread safe way and broadcast if needed. + /// + /// @param[in] bits + /// The bits to clear in \a m_value. + /// + /// @param[in] broadcast_type + /// A value indicating when and if to broadast. See the + /// PredicateBroadcastType enumeration for details. + /// + /// @see Predicate::Broadcast() + //------------------------------------------------------------------ + void + ResetValueBits (T bits, PredicateBroadcastType broadcast_type) + { + Mutex::Locker locker(m_mutex); +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (bits = 0x%8.8x, broadcast_type = %i)\n", __FUNCTION__, bits, broadcast_type); +#endif + const T old_value = m_value; + m_value &= ~bits; + + Broadcast(old_value, broadcast_type); + } + + //------------------------------------------------------------------ + /// Wait for bits to be set in \a m_value. + /// + /// Waits in a thread safe way for any bits in \a bits to get + /// logically set in \a m_value. If any bits are already set in + /// \a m_value, this function will return without waiting. + /// + /// It is possible for the value to be changed between the time + /// the bits are set and the time the waiting thread wakes up. + /// If the bits are no longer set when the waiting thread wakes + /// up, it will go back into a wait state. It may be necessary + /// for the calling code to use additional thread synchronization + /// methods to detect transitory states. + /// + /// @param[in] bits + /// The bits we are waiting to be set in \a m_value. + /// + /// @param[in] abstime + /// If non-NULL, the absolute time at which we should stop + /// waiting, else wait an infinite amount of time. + /// + /// @return + /// Any bits of the requested bits that actually were set within + /// the time specified. Zero if a timeout or unrecoverable error + /// occurred. + //------------------------------------------------------------------ + T + WaitForSetValueBits (T bits, const TimeValue *abstime = NULL) + { + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (Mutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + Mutex::Locker locker(m_mutex); +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (bits = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, bits, abstime, m_value); +#endif + while (err == 0 && ((m_value & bits) == 0)) + { + err = m_condition.Wait (m_mutex, abstime); + } +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n", __FUNCTION__, bits, m_value, m_value & bits); +#endif + + return m_value & bits; + } + + //------------------------------------------------------------------ + /// Wait for bits to be reset in \a m_value. + /// + /// Waits in a thread safe way for any bits in \a bits to get + /// logically reset in \a m_value. If all bits are already reset in + /// \a m_value, this function will return without waiting. + /// + /// It is possible for the value to be changed between the time + /// the bits are reset and the time the waiting thread wakes up. + /// If the bits are no set when the waiting thread wakes up, it will + /// go back into a wait state. It may be necessary for the calling + /// code to use additional thread synchronization methods to detect + /// transitory states. + /// + /// @param[in] bits + /// The bits we are waiting to be reset in \a m_value. + /// + /// @param[in] abstime + /// If non-NULL, the absolute time at which we should stop + /// waiting, else wait an infinite amount of time. + /// + /// @return + /// Zero on successful waits, or non-zero if a timeout or + /// unrecoverable error occurs. + //------------------------------------------------------------------ + T + WaitForResetValueBits (T bits, const TimeValue *abstime = NULL) + { + int err = 0; + + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (Mutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + Mutex::Locker locker(m_mutex); + +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (bits = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, bits, abstime, m_value); +#endif + while (err == 0 && ((m_value & bits) != 0)) + { + err = m_condition.Wait (m_mutex, abstime); + } + +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (bits = 0x%8.8x), m_value = 0x%8.8x, returning 0x%8.8x\n", __FUNCTION__, bits, m_value, m_value & bits); +#endif + return m_value & bits; + } + + //------------------------------------------------------------------ + /// Wait for \a m_value to be equal to \a value. + /// + /// Waits in a thread safe way for \a m_value to be equal to \a + /// value. If \a m_value is already equal to \a value, this + /// function will return without waiting. + /// + /// It is possible for the value to be changed between the time + /// the value is set and the time the waiting thread wakes up. + /// If the value no longer matches the requested value when the + /// waiting thread wakes up, it will go back into a wait state. It + /// may be necessary for the calling code to use additional thread + /// synchronization methods to detect transitory states. + /// + /// @param[in] value + /// The value we want \a m_value to be equal to. + /// + /// @param[in] abstime + /// If non-NULL, the absolute time at which we should stop + /// waiting, else wait an infinite amount of time. + /// + /// @param[out] timed_out + /// If not null, set to true if we return because of a time out, + /// and false if the value was set. + /// + /// @return + /// @li \b true if the \a m_value is equal to \a value + /// @li \b false otherwise + //------------------------------------------------------------------ + bool + WaitForValueEqualTo (T value, const TimeValue *abstime = NULL, bool *timed_out = NULL) + { + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (Mutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + Mutex::Locker locker(m_mutex); + +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, value, abstime, m_value); +#endif + if (timed_out) + *timed_out = false; + + while (err == 0 && m_value != value) + { + err = m_condition.Wait (m_mutex, abstime, timed_out); + } + + return m_value == value; + } + + //------------------------------------------------------------------ + /// Wait for \a m_value to be equal to \a value and then set it to + /// a new value. + /// + /// Waits in a thread safe way for \a m_value to be equal to \a + /// value and then sets \a m_value to \a new_value. If \a m_value + /// is already equal to \a value, this function will immediately + /// set \a m_value to \a new_value and return without waiting. + /// + /// It is possible for the value to be changed between the time + /// the value is set and the time the waiting thread wakes up. + /// If the value no longer matches the requested value when the + /// waiting thread wakes up, it will go back into a wait state. It + /// may be necessary for the calling code to use additional thread + /// synchronization methods to detect transitory states. + /// + /// @param[in] value + /// The value we want \a m_value to be equal to. + /// + /// @param[in] new_value + /// The value to which \a m_value will be set if \b true is + /// returned. + /// + /// @param[in] abstime + /// If non-NULL, the absolute time at which we should stop + /// waiting, else wait an infinite amount of time. + /// + /// @param[out] timed_out + /// If not null, set to true if we return because of a time out, + /// and false if the value was set. + /// + /// @return + /// @li \b true if the \a m_value became equal to \a value + /// @li \b false otherwise + //------------------------------------------------------------------ + bool + WaitForValueEqualToAndSetValueTo (T wait_value, T new_value, const TimeValue *abstime = NULL, bool *timed_out = NULL) + { + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (Mutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + Mutex::Locker locker(m_mutex); + +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (wait_value = 0x%8.8x, new_value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, wait_value, new_value, abstime, m_value); +#endif + if (timed_out) + *timed_out = false; + + while (err == 0 && m_value != wait_value) + { + err = m_condition.Wait (m_mutex, abstime, timed_out); + } + + if (m_value == wait_value) + { + m_value = new_value; + return true; + } + + return false; + } + + + //------------------------------------------------------------------ + /// Wait for \a m_value to not be equal to \a value. + /// + /// Waits in a thread safe way for \a m_value to not be equal to \a + /// value. If \a m_value is already not equal to \a value, this + /// function will return without waiting. + /// + /// It is possible for the value to be changed between the time + /// the value is set and the time the waiting thread wakes up. + /// If the value is equal to the test value when the waiting thread + /// wakes up, it will go back into a wait state. It may be + /// necessary for the calling code to use additional thread + /// synchronization methods to detect transitory states. + /// + /// @param[in] value + /// The value we want \a m_value to not be equal to. + /// + /// @param[out] new_value + /// The new value if \b true is returned. + /// + /// @param[in] abstime + /// If non-NULL, the absolute time at which we should stop + /// waiting, else wait an infinite amount of time. + /// + /// @return + /// @li \b true if the \a m_value is equal to \a value + /// @li \b false otherwise + //------------------------------------------------------------------ + bool + WaitForValueNotEqualTo (T value, T &new_value, const TimeValue *abstime = NULL) + { + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (Mutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + Mutex::Locker locker(m_mutex); +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (value = 0x%8.8x, abstime = %p), m_value = 0x%8.8x\n", __FUNCTION__, value, abstime, m_value); +#endif + while (err == 0 && m_value == value) + { + err = m_condition.Wait (m_mutex, abstime); + } + + if (m_value != value) + { + new_value = m_value; + return true; + } + return false; + } + +protected: + //---------------------------------------------------------------------- + // pthread condition and mutex variable to controll access and allow + // blocking between the main thread and the spotlight index thread. + //---------------------------------------------------------------------- + T m_value; ///< The templatized value T that we are protecting access to + mutable Mutex m_mutex; ///< The mutex to use when accessing the data + Condition m_condition; ///< The pthread condition variable to use for signaling that data available or changed. + +private: + + //------------------------------------------------------------------ + /// Broadcast if needed. + /// + /// Check to see if we need to broadcast to our condition variable + /// depedning on the \a old_value and on the \a broadcast_type. + /// + /// If \a broadcast_type is eBroadcastNever, no broadcast will be + /// sent. + /// + /// If \a broadcast_type is eBroadcastAlways, the condition variable + /// will always be broadcast. + /// + /// If \a broadcast_type is eBroadcastOnChange, the condition + /// variable be broadcast if the owned value changes. + //------------------------------------------------------------------ + void + Broadcast (T old_value, PredicateBroadcastType broadcast_type) + { + bool broadcast = (broadcast_type == eBroadcastAlways) || ((broadcast_type == eBroadcastOnChange) && old_value != m_value); +#ifdef DB_PTHREAD_LOG_EVENTS + printf("%s (old_value = 0x%8.8x, broadcast_type = %i) m_value = 0x%8.8x, broadcast = %u\n", __FUNCTION__, old_value, broadcast_type, m_value, broadcast); +#endif + if (broadcast) + m_condition.Broadcast(); + } + + + DISALLOW_COPY_AND_ASSIGN(Predicate); +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // #ifndef liblldb_Predicate_h_ diff --git a/include/lldb/Host/ProcessRunLock.h b/include/lldb/Host/ProcessRunLock.h new file mode 100644 index 0000000..f563be73 --- /dev/null +++ b/include/lldb/Host/ProcessRunLock.h @@ -0,0 +1,165 @@ +//===-- ProcessRunLock.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_ProcessRunLock_h_ +#define liblldb_ProcessRunLock_h_ +#if defined(__cplusplus) + +#include "lldb/Host/Mutex.h" +#include "lldb/Host/Condition.h" +#include <pthread.h> +#include <stdint.h> +#include <time.h> + +//---------------------------------------------------------------------- +/// Enumerations for broadcasting. +//---------------------------------------------------------------------- +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ProcessRunLock ProcessRunLock.h "lldb/Host/ProcessRunLock.h" +/// @brief A class used to prevent the process from starting while other +/// threads are accessing its data, and prevent access to its data while +/// it is running. +//---------------------------------------------------------------------- + +class ProcessRunLock +{ +public: + ProcessRunLock () : + m_rwlock(), + m_running(false) + { + int err = ::pthread_rwlock_init(&m_rwlock, NULL); (void)err; +//#if LLDB_CONFIGURATION_DEBUG +// assert(err == 0); +//#endif + } + + ~ProcessRunLock () + { + int err = ::pthread_rwlock_destroy (&m_rwlock); (void)err; +//#if LLDB_CONFIGURATION_DEBUG +// assert(err == 0); +//#endif + } + + bool + ReadTryLock () + { + ::pthread_rwlock_rdlock (&m_rwlock); + if (m_running == false) + { + return true; + } + ::pthread_rwlock_unlock (&m_rwlock); + return false; + } + + bool + ReadUnlock () + { + return ::pthread_rwlock_unlock (&m_rwlock) == 0; + } + + bool + SetRunning() + { + ::pthread_rwlock_wrlock (&m_rwlock); + m_running = true; + ::pthread_rwlock_unlock (&m_rwlock); + return true; + } + + bool + TrySetRunning() + { + bool r; + + if (::pthread_rwlock_trywrlock (&m_rwlock) == 0) + { + r = !m_running; + m_running = true; + ::pthread_rwlock_unlock (&m_rwlock); + return r; + } + return false; + } + + bool + SetStopped () + { + ::pthread_rwlock_wrlock (&m_rwlock); + m_running = false; + ::pthread_rwlock_unlock (&m_rwlock); + return true; + } + + class ProcessRunLocker + { + public: + ProcessRunLocker () : + m_lock (NULL) + { + } + + ~ProcessRunLocker() + { + Unlock(); + } + + // Try to lock the read lock, but only do so if there are no writers. + bool + TryLock (ProcessRunLock *lock) + { + if (m_lock) + { + if (m_lock == lock) + return true; // We already have this lock locked + else + Unlock(); + } + if (lock) + { + if (lock->ReadTryLock()) + { + m_lock = lock; + return true; + } + } + return false; + } + + protected: + void + Unlock () + { + if (m_lock) + { + m_lock->ReadUnlock(); + m_lock = NULL; + } + } + + ProcessRunLock *m_lock; + private: + DISALLOW_COPY_AND_ASSIGN(ProcessRunLocker); + }; + +protected: + pthread_rwlock_t m_rwlock; + bool m_running; +private: + DISALLOW_COPY_AND_ASSIGN(ProcessRunLock); +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // #ifndef liblldb_ProcessRunLock_h_ diff --git a/include/lldb/Host/SocketAddress.h b/include/lldb/Host/SocketAddress.h new file mode 100644 index 0000000..e63b238 --- /dev/null +++ b/include/lldb/Host/SocketAddress.h @@ -0,0 +1,256 @@ +//===-- SocketAddress.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_SocketAddress_h_ +#define liblldb_SocketAddress_h_ + +// C Includes +#include <stdint.h> +#include <sys/socket.h> +#include <netdb.h> +#include <netinet/in.h> + +#if defined(__FreeBSD__) +#include <sys/types.h> +#endif + +// C++ Includes +// Other libraries and framework includes +// Project includes + +namespace lldb_private { + +class SocketAddress +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SocketAddress (); + SocketAddress (const struct sockaddr &s); + SocketAddress (const struct sockaddr_in &s); + SocketAddress (const struct sockaddr_in6 &s); + SocketAddress (const struct sockaddr_storage &s); + SocketAddress (const SocketAddress& rhs); + ~SocketAddress (); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const SocketAddress& + operator=(const SocketAddress& rhs); + + const SocketAddress& + operator=(const struct addrinfo *addr_info); + + const SocketAddress& + operator=(const struct sockaddr &s); + + const SocketAddress& + operator=(const struct sockaddr_in &s); + + const SocketAddress& + operator=(const struct sockaddr_in6 &s); + + const SocketAddress& + operator=(const struct sockaddr_storage &s); + + //------------------------------------------------------------------ + // Clear the contents of this socket address + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + // Get the length for the current socket address family + //------------------------------------------------------------------ + socklen_t + GetLength () const; + + //------------------------------------------------------------------ + // Get the mex length for the the largest socket address supported. + //------------------------------------------------------------------ + static socklen_t + GetMaxLength (); + + //------------------------------------------------------------------ + // Get the socket address family + //------------------------------------------------------------------ + sa_family_t + GetFamily () const; + + //------------------------------------------------------------------ + // Set the socket address family + //------------------------------------------------------------------ + void + SetFamily (sa_family_t family); + + //------------------------------------------------------------------ + // Get the port if the socket address for the family has a port + //------------------------------------------------------------------ + in_port_t + GetPort () const; + + //------------------------------------------------------------------ + // Set the port if the socket address for the family has a port. + // The family must be set correctly prior to calling this function. + //------------------------------------------------------------------ + bool + SetPort (in_port_t port); + + //------------------------------------------------------------------ + // Set the socket address according to the first match from a call + // to getaddrinfo() (or equivalent functions for systems that don't + // have getaddrinfo(). If "addr_info_ptr" is not NULL, it will get + // filled in with the match that was used to populate this socket + // address. + //------------------------------------------------------------------ + bool + SetAddress (const struct addrinfo *hints_ptr, // Optional hints where the family, protocol and other things can be specified. + const char *host, // Hostname ("foo.bar.com" or "foo" or IP address string ("123.234.12.1" or "2001:0db8:85a3:0000:0000:8a2e:0370:7334") + const char *service, // Protocol name ("tcp", "http", etc) or a raw port number string ("81") + struct addrinfo *addr_info_ptr); // If non-NULL, this will get filled in with the match + + //------------------------------------------------------------------ + // Quick way to set the SocketAddress to localhost given the family. + // Returns true if successful, false if "family" doesn't support + // localhost or if "family" is not supported by this class. + //------------------------------------------------------------------ + bool + SetToLocalhost (sa_family_t family, + in_port_t port); + + //------------------------------------------------------------------ + // Returns true if there is a valid socket address in this object. + //------------------------------------------------------------------ + bool + IsValid () const; + + //------------------------------------------------------------------ + // Direct access to all of the sockaddr structures + //------------------------------------------------------------------ + struct sockaddr & + sockaddr () + { + return m_socket_addr.sa; + } + + const struct sockaddr & + sockaddr () const + { + return m_socket_addr.sa; + } + + struct sockaddr_in & + sockaddr_in () + { + return m_socket_addr.sa_ipv4; + } + + const struct sockaddr_in & + sockaddr_in () const + { + return m_socket_addr.sa_ipv4; + } + + struct sockaddr_in6 & + sockaddr_in6 () + { + return m_socket_addr.sa_ipv6; + } + + const struct sockaddr_in6 & + sockaddr_in6 () const + { + return m_socket_addr.sa_ipv6; + } + + struct sockaddr_storage & + sockaddr_storage () + { + return m_socket_addr.sa_storage; + } + + + const struct sockaddr_storage & + sockaddr_storage () const + { + return m_socket_addr.sa_storage; + } + + + //------------------------------------------------------------------ + // Conversion operators to allow getting the contents of this class + // as a pointer to the appropriate structure. This allows an instance + // of this class to be used in calls that take one of the sockaddr + // structure variants without having to manally use the correct + // accessor function. + //------------------------------------------------------------------ + + operator struct sockaddr * () + { + return &m_socket_addr.sa; + } + + operator const struct sockaddr * () const + { + return &m_socket_addr.sa; + } + + operator struct sockaddr_in * () + { + return &m_socket_addr.sa_ipv4; + } + + operator const struct sockaddr_in * () const + { + return &m_socket_addr.sa_ipv4; + } + + operator struct sockaddr_in6 * () + { + return &m_socket_addr.sa_ipv6; + } + + operator const struct sockaddr_in6 * () const + { + return &m_socket_addr.sa_ipv6; + } + + operator const struct sockaddr_storage * () const + { + return &m_socket_addr.sa_storage; + } + + operator struct sockaddr_storage * () + { + return &m_socket_addr.sa_storage; + } + + +protected: + typedef union sockaddr_tag + { + struct sockaddr sa; + struct sockaddr_in sa_ipv4; + struct sockaddr_in6 sa_ipv6; + struct sockaddr_storage sa_storage; + } sockaddr_t; + + //------------------------------------------------------------------ + // Classes that inherit from SocketAddress can see and modify these + //------------------------------------------------------------------ + sockaddr_t m_socket_addr; +}; + + +} // namespace lldb_private + + +#endif // liblldb_SocketAddress_h_ diff --git a/include/lldb/Host/Symbols.h b/include/lldb/Host/Symbols.h new file mode 100644 index 0000000..9db68e1 --- /dev/null +++ b/include/lldb/Host/Symbols.h @@ -0,0 +1,69 @@ +//===-- Symbols.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_Symbols_h_ +#define liblldb_Symbols_h_ + +// C Includes +#include <stdint.h> +#include <sys/time.h> + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Host/FileSpec.h" + +namespace lldb_private { + +class Symbols +{ +public: + //---------------------------------------------------------------------- + // Locate the executable file given a module specification. + // + // Locating the file should happen only on the local computer or using + // the current computers global settings. + //---------------------------------------------------------------------- + static FileSpec + LocateExecutableObjectFile (const ModuleSpec &module_spec); + + //---------------------------------------------------------------------- + // Locate the symbol file given a module specification. + // + // Locating the file should happen only on the local computer or using + // the current computers global settings. + //---------------------------------------------------------------------- + static FileSpec + LocateExecutableSymbolFile (const ModuleSpec &module_spec); + + static FileSpec + FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec, + const lldb_private::UUID *uuid, + const ArchSpec *arch); + + //---------------------------------------------------------------------- + // Locate the object and symbol file given a module specification. + // + // Locating the file can try to download the file from a corporate build + // respository, or using any other means necessary to locate both the + // unstripped object file and the debug symbols. + // The force_lookup argument controls whether the external program is called + // unconditionally to find the symbol file, or if the user's settings are + // checked to see if they've enabled the external program before calling. + // + //---------------------------------------------------------------------- + static bool + DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup = true); + +}; + +} // namespace lldb_private + + +#endif // liblldb_Symbols_h_ diff --git a/include/lldb/Host/Terminal.h b/include/lldb/Host/Terminal.h new file mode 100644 index 0000000..b334717 --- /dev/null +++ b/include/lldb/Host/Terminal.h @@ -0,0 +1,254 @@ +//===-- Terminal.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_Terminal_h_ +#define liblldb_Terminal_h_ +#if defined(__cplusplus) + +#include "lldb/lldb-private.h" + +struct termios; + +namespace lldb_private { + +class Terminal +{ +public: + + Terminal (int fd = -1) : + m_fd (fd) + { + } + + ~Terminal () + { + } + + bool + IsATerminal () const; + + int + GetFileDescriptor () const + { + return m_fd; + } + + void + SetFileDescriptor (int fd) + { + m_fd = fd; + } + + bool + FileDescriptorIsValid () const + { + return m_fd != -1; + } + + void + Clear () + { + m_fd = -1; + } + + bool + SetEcho (bool enabled); + + bool + SetCanonical (bool enabled); + +protected: + int m_fd; // This may or may not be a terminal file descriptor +}; + + +//---------------------------------------------------------------------- +/// @class State Terminal.h "lldb/Host/Terminal.h" +/// @brief A terminal state saving/restoring class. +/// +/// This class can be used to remember the terminal state for a file +/// descriptor and later restore that state as it originally was. +//---------------------------------------------------------------------- +class TerminalState +{ +public: + //------------------------------------------------------------------ + /// Default constructor + //------------------------------------------------------------------ + TerminalState(); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~TerminalState(); + + //------------------------------------------------------------------ + /// Save the TTY state for \a fd. + /// + /// Save the current state of the TTY for the file descriptor "fd" + /// and if "save_process_group" is true, attempt to save the process + /// group info for the TTY. + /// + /// @param[in] fd + /// The file descriptor to save the state of. + /// + /// @param[in] save_process_group + /// If \b true, save the process group settings, else do not + /// save the process group setttings for a TTY. + /// + /// @return + /// Returns \b true if \a fd describes a TTY and if the state + /// was able to be saved, \b false otherwise. + //------------------------------------------------------------------ + bool + Save (int fd, bool save_process_group); + + //------------------------------------------------------------------ + /// Restore the TTY state to the cached state. + /// + /// Restore the state of the TTY using the cached values from a + /// previous call to TerminalState::Save(int,bool). + /// + /// @return + /// Returns \b true if the TTY state was successfully restored, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + Restore () const; + + //------------------------------------------------------------------ + /// Test for valid cached TTY state information. + /// + /// @return + /// Returns \b true if this object has valid saved TTY state + /// settings that can be used to restore a previous state, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + IsValid() const; + + void + Clear (); + +protected: + + //------------------------------------------------------------------ + /// Test if tflags is valid. + /// + /// @return + /// Returns \b true if \a m_tflags is valid and can be restored, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + TFlagsIsValid() const; + + //------------------------------------------------------------------ + /// Test if ttystate is valid. + /// + /// @return + /// Returns \b true if \a m_ttystate is valid and can be + /// restored, \b false otherwise. + //------------------------------------------------------------------ + bool + TTYStateIsValid() const; + + //------------------------------------------------------------------ + /// Test if the process group information is valid. + /// + /// @return + /// Returns \b true if \a m_process_group is valid and can be + /// restored, \b false otherwise. + //------------------------------------------------------------------ + bool + ProcessGroupIsValid() const; + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + Terminal m_tty; ///< A terminal + int m_tflags; ///< Cached tflags information. + std::unique_ptr<struct termios> m_termios_ap; ///< Cached terminal state information. + lldb::pid_t m_process_group;///< Cached process group information. + +}; + +//---------------------------------------------------------------------- +/// @class TerminalStateSwitcher Terminal.h "lldb/Host/Terminal.h" +/// @brief A TTY state switching class. +/// +/// This class can be used to remember 2 TTY states for a given file +/// descriptor and switch between the two states. +//---------------------------------------------------------------------- +class TerminalStateSwitcher +{ +public: + //------------------------------------------------------------------ + /// Constructor + //------------------------------------------------------------------ + TerminalStateSwitcher(); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~TerminalStateSwitcher(); + + //------------------------------------------------------------------ + /// Get the number of possible states to save. + /// + /// @return + /// The number of states that this TTY switcher object contains. + //------------------------------------------------------------------ + uint32_t + GetNumberOfStates() const; + + //------------------------------------------------------------------ + /// Restore the TTY state for state at index \a idx. + /// + /// @return + /// Returns \b true if the TTY state was successfully restored, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + Restore (uint32_t idx) const; + + //------------------------------------------------------------------ + /// Save the TTY state information for the state at index \a idx. + /// The TTY state is saved for the file descriptor \a fd and + /// the process group information will also be saved if requested + /// by \a save_process_group. + /// + /// @param[in] idx + /// The index into the state array where the state should be + /// saved. + /// + /// @param[in] fd + /// The file descriptor for which to save the settings. + /// + /// @param[in] save_process_group + /// If \b true, save the process group information for the TTY. + /// + /// @return + /// Returns \b true if the save was successful, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + Save (uint32_t idx, int fd, bool save_process_group); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + mutable uint32_t m_currentState; ///< The currently active TTY state index. + TerminalState m_ttystates[2]; ///< The array of TTY states that holds saved TTY info. +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // #ifndef liblldb_Terminal_h_ diff --git a/include/lldb/Host/TimeValue.h b/include/lldb/Host/TimeValue.h new file mode 100644 index 0000000..8c43d6d --- /dev/null +++ b/include/lldb/Host/TimeValue.h @@ -0,0 +1,107 @@ +//===-- TimeValue.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_TimeValue_h_ +#define liblldb_TimeValue_h_ + +// C Includes +#include <stdint.h> +#include <sys/time.h> + +// BEGIN: MinGW work around +#if !defined(_STRUCT_TIMESPEC) && !defined(HAVE_STRUCT_TIMESPEC) +#include <pthread.h> +#endif +// END: MinGW work around + +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class TimeValue +{ +public: + static const uint64_t MicroSecPerSec = 1000000UL; + static const uint64_t NanoSecPerSec = 1000000000UL; + static const uint64_t NanoSecPerMicroSec = 1000U; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + TimeValue(); + TimeValue(const TimeValue& rhs); + TimeValue(const struct timespec& ts); + TimeValue(const struct timeval& tv); + ~TimeValue(); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const TimeValue& + operator=(const TimeValue& rhs); + + void + Clear (); + + uint64_t + GetAsNanoSecondsSinceJan1_1970() const; + + uint64_t + GetAsMicroSecondsSinceJan1_1970() const; + + uint64_t + GetAsSecondsSinceJan1_1970() const; + + struct timespec + GetAsTimeSpec () const; + + struct timeval + GetAsTimeVal () const; + + bool + IsValid () const; + + void + OffsetWithSeconds (uint64_t sec); + + void + OffsetWithMicroSeconds (uint64_t usec); + + void + OffsetWithNanoSeconds (uint64_t nsec); + + static TimeValue + Now(); + + void + Dump (Stream *s, uint32_t width = 0) const; + +protected: + //------------------------------------------------------------------ + // Classes that inherit from TimeValue can see and modify these + //------------------------------------------------------------------ + uint64_t m_nano_seconds; +}; + +bool operator == (const TimeValue &lhs, const TimeValue &rhs); +bool operator != (const TimeValue &lhs, const TimeValue &rhs); +bool operator < (const TimeValue &lhs, const TimeValue &rhs); +bool operator <= (const TimeValue &lhs, const TimeValue &rhs); +bool operator > (const TimeValue &lhs, const TimeValue &rhs); +bool operator >= (const TimeValue &lhs, const TimeValue &rhs); + +uint64_t operator -(const TimeValue &lhs, const TimeValue &rhs); + +} // namespace lldb_private + + +#endif // liblldb_TimeValue_h_ diff --git a/include/lldb/Host/freebsd/Config.h b/include/lldb/Host/freebsd/Config.h new file mode 100644 index 0000000..49d97dd --- /dev/null +++ b/include/lldb/Host/freebsd/Config.h @@ -0,0 +1,28 @@ +//===-- Config.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//---------------------------------------------------------------------- +// LLDB currently doesn't have a dynamic configuration mechanism, so we +// are going to hardcode things for now. Eventually these files will +// be auto generated by some configuration script that can detect +// platform functionality availability. +//---------------------------------------------------------------------- + +#ifndef liblldb_Platform_Config_h_ +#define liblldb_Platform_Config_h_ + +#define LLDB_CONFIG_TERMIOS_SUPPORTED 1 + +#define LLDB_CONFIG_TILDE_RESOLVES_TO_USER 1 + +//#define LLDB_CONFIG_DLOPEN_RTLD_FIRST_SUPPORTED 1 + +//#define LLDB_CONFIG_FCNTL_GETPATH_SUPPORTED 1 + +#endif // #ifndef liblldb_Platform_Config_h_ diff --git a/include/lldb/Interpreter/Args.h b/include/lldb/Interpreter/Args.h new file mode 100644 index 0000000..d06c3e5 --- /dev/null +++ b/include/lldb/Interpreter/Args.h @@ -0,0 +1,467 @@ +//===-- Args.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_Command_h_ +#define liblldb_Command_h_ + +// C Includes +#include <getopt.h> + +// C++ Includes +#include <list> +#include <string> +#include <vector> +#include <utility> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private-types.h" +#include "lldb/lldb-types.h" +#include "lldb/Core/Error.h" + +namespace lldb_private { + +typedef std::pair<int, std::string> OptionArgValue; +typedef std::pair<std::string, OptionArgValue> OptionArgPair; +typedef std::vector<OptionArgPair> OptionArgVector; +typedef std::shared_ptr<OptionArgVector> OptionArgVectorSP; + +struct OptionArgElement +{ + enum { + eUnrecognizedArg = -1, + eBareDash = -2, + eBareDoubleDash = -3 + }; + + OptionArgElement (int defs_index, int pos, int arg_pos) : + opt_defs_index(defs_index), + opt_pos (pos), + opt_arg_pos (arg_pos) + { + } + + int opt_defs_index; + int opt_pos; + int opt_arg_pos; +}; + +typedef std::vector<OptionArgElement> OptionElementVector; + +//---------------------------------------------------------------------- +/// @class Args Args.h "lldb/Interpreter/Args.h" +/// @brief A command line argument class. +/// +/// The Args class is designed to be fed a command line. The +/// command line is copied into an internal buffer and then split up +/// into arguments. Arguments are space delimited if there are no quotes +/// (single, double, or backtick quotes) surrounding the argument. Spaces +/// can be escaped using a \ character to avoid having to surround an +/// argument that contains a space with quotes. +//---------------------------------------------------------------------- +class Args +{ +public: + + //------------------------------------------------------------------ + /// Construct with an option command string. + /// + /// @param[in] command + /// A NULL terminated command that will be copied and split up + /// into arguments. + /// + /// @see Args::SetCommandString(const char *) + //------------------------------------------------------------------ + Args (const char *command = NULL); + + Args (const char *command, size_t len); + + Args (const Args &rhs); + + const Args & + operator= (const Args &rhs); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~Args(); + + //------------------------------------------------------------------ + /// Dump all arguments to the stream \a s. + /// + /// @param[in] s + /// The stream to which to dump all arguments in the argument + /// vector. + //------------------------------------------------------------------ + void + Dump (Stream *s); + + //------------------------------------------------------------------ + /// Sets the command string contained by this object. + /// + /// The command string will be copied and split up into arguments + /// that can be accessed via the accessor functions. + /// + /// @param[in] command + /// A NULL terminated command that will be copied and split up + /// into arguments. + /// + /// @see Args::GetArgumentCount() const + /// @see Args::GetArgumentAtIndex (size_t) const + /// @see Args::GetArgumentVector () + /// @see Args::Shift () + /// @see Args::Unshift (const char *) + //------------------------------------------------------------------ + void + SetCommandString (const char *command); + + void + SetCommandString (const char *command, size_t len); + + bool + GetCommandString (std::string &command) const; + + bool + GetQuotedCommandString (std::string &command) const; + + //------------------------------------------------------------------ + /// Gets the number of arguments left in this command object. + /// + /// @return + /// The number or arguments in this object. + //------------------------------------------------------------------ + size_t + GetArgumentCount () const; + + //------------------------------------------------------------------ + /// Gets the NULL terminated C string argument pointer for the + /// argument at index \a idx. + /// + /// @return + /// The NULL terminated C string argument pointer if \a idx is a + /// valid argument index, NULL otherwise. + //------------------------------------------------------------------ + const char * + GetArgumentAtIndex (size_t idx) const; + + char + GetArgumentQuoteCharAtIndex (size_t idx) const; + + //------------------------------------------------------------------ + /// Gets the argument vector. + /// + /// The value returned by this function can be used by any function + /// that takes and vector. The return value is just like \a argv + /// in the standard C entry point function: + /// \code + /// int main (int argc, const char **argv); + /// \endcode + /// + /// @return + /// An array of NULL terminated C string argument pointers that + /// also has a terminating NULL C string pointer + //------------------------------------------------------------------ + char ** + GetArgumentVector (); + + //------------------------------------------------------------------ + /// Gets the argument vector. + /// + /// The value returned by this function can be used by any function + /// that takes and vector. The return value is just like \a argv + /// in the standard C entry point function: + /// \code + /// int main (int argc, const char **argv); + /// \endcode + /// + /// @return + /// An array of NULL terminate C string argument pointers that + /// also has a terminating NULL C string pointer + //------------------------------------------------------------------ + const char ** + GetConstArgumentVector () const; + + + //------------------------------------------------------------------ + /// Appends a new argument to the end of the list argument list. + /// + /// @param[in] arg_cstr + /// The new argument as a NULL terminated C string. + /// + /// @param[in] quote_char + /// If the argument was originally quoted, put in the quote char here. + /// + /// @return + /// The NULL terminated C string of the copy of \a arg_cstr. + //------------------------------------------------------------------ + const char * + AppendArgument (const char *arg_cstr, char quote_char = '\0'); + + void + AppendArguments (const Args &rhs); + + void + AppendArguments (const char **argv); + + //------------------------------------------------------------------ + /// Insert the argument value at index \a idx to \a arg_cstr. + /// + /// @param[in] idx + /// The index of where to insert the argument. + /// + /// @param[in] arg_cstr + /// The new argument as a NULL terminated C string. + /// + /// @param[in] quote_char + /// If the argument was originally quoted, put in the quote char here. + /// + /// @return + /// The NULL terminated C string of the copy of \a arg_cstr. + //------------------------------------------------------------------ + const char * + InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char = '\0'); + + //------------------------------------------------------------------ + /// Replaces the argument value at index \a idx to \a arg_cstr + /// if \a idx is a valid argument index. + /// + /// @param[in] idx + /// The index of the argument that will have its value replaced. + /// + /// @param[in] arg_cstr + /// The new argument as a NULL terminated C string. + /// + /// @param[in] quote_char + /// If the argument was originally quoted, put in the quote char here. + /// + /// @return + /// The NULL terminated C string of the copy of \a arg_cstr if + /// \a idx was a valid index, NULL otherwise. + //------------------------------------------------------------------ + const char * + ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char = '\0'); + + //------------------------------------------------------------------ + /// Deletes the argument value at index + /// if \a idx is a valid argument index. + /// + /// @param[in] idx + /// The index of the argument that will have its value replaced. + /// + //------------------------------------------------------------------ + void + DeleteArgumentAtIndex (size_t idx); + + //------------------------------------------------------------------ + /// Sets the argument vector value, optionally copying all + /// arguments into an internal buffer. + /// + /// Sets the arguments to match those found in \a argv. All argument + /// strings will be copied into an internal buffers. + // + // FIXME: Handle the quote character somehow. + //------------------------------------------------------------------ + void + SetArguments (size_t argc, const char **argv); + + void + SetArguments (const char **argv); + + //------------------------------------------------------------------ + /// Shifts the first argument C string value of the array off the + /// argument array. + /// + /// The string value will be freed, so a copy of the string should + /// be made by calling Args::GetArgumentAtIndex (size_t) const + /// first and copying the returned value before calling + /// Args::Shift(). + /// + /// @see Args::GetArgumentAtIndex (size_t) const + //------------------------------------------------------------------ + void + Shift (); + + //------------------------------------------------------------------ + /// Inserts a class owned copy of \a arg_cstr at the beginning of + /// the argument vector. + /// + /// A copy \a arg_cstr will be made. + /// + /// @param[in] arg_cstr + /// The argument to push on the front the the argument stack. + /// + /// @param[in] quote_char + /// If the argument was originally quoted, put in the quote char here. + /// + /// @return + /// A pointer to the copy of \a arg_cstr that was made. + //------------------------------------------------------------------ + const char * + Unshift (const char *arg_cstr, char quote_char = '\0'); + + //------------------------------------------------------------------ + /// Parse the arguments in the contained arguments. + /// + /// The arguments that are consumed by the argument parsing process + /// will be removed from the argument vector. The arguements that + /// get processed start at the second argument. The first argument + /// is assumed to be the command and will not be touched. + /// + /// @see class Options + //------------------------------------------------------------------ + Error + ParseOptions (Options &options); + + size_t + FindArgumentIndexForOption (struct option *long_options, int long_options_index); + + bool + IsPositionalArgument (const char *arg); + + // The following works almost identically to ParseOptions, except that no option is required to have arguments, + // and it builds up the option_arg_vector as it parses the options. + + void + ParseAliasOptions (Options &options, CommandReturnObject &result, OptionArgVector *option_arg_vector, + std::string &raw_input_line); + + void + ParseArgsForCompletion (Options &options, OptionElementVector &option_element_vector, uint32_t cursor_index); + + //------------------------------------------------------------------ + // Clear the arguments. + // + // For re-setting or blanking out the list of arguments. + //------------------------------------------------------------------ + void + Clear (); + + static const char * + StripSpaces (std::string &s, + bool leading = true, + bool trailing = true, + bool return_null_if_empty = true); + + static int32_t + StringToSInt32 (const char *s, int32_t fail_value = 0, int base = 0, bool *success_ptr = NULL); + + static uint32_t + StringToUInt32 (const char *s, uint32_t fail_value = 0, int base = 0, bool *success_ptr = NULL); + + static int64_t + StringToSInt64 (const char *s, int64_t fail_value = 0, int base = 0, bool *success_ptr = NULL); + + static uint64_t + StringToUInt64 (const char *s, uint64_t fail_value = 0, int base = 0, bool *success_ptr = NULL); + + static bool + UInt64ValueIsValidForByteSize (uint64_t uval64, size_t total_byte_size) + { + if (total_byte_size > 8) + return false; + + if (total_byte_size == 8) + return true; + + const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1; + return uval64 <= max; + } + + static bool + SInt64ValueIsValidForByteSize (int64_t sval64, size_t total_byte_size) + { + if (total_byte_size > 8) + return false; + + if (total_byte_size == 8) + return true; + + const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1; + const int64_t min = ~(max); + return min <= sval64 && sval64 <= max; + } + + static lldb::addr_t + StringToAddress (const ExecutionContext *exe_ctx, + const char *s, + lldb::addr_t fail_value, + Error *error); + + static bool + StringToBoolean (const char *s, bool fail_value, bool *success_ptr); + + static int64_t + StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error); + + static lldb::ScriptLanguage + StringToScriptLanguage (const char *s, lldb::ScriptLanguage fail_value, bool *success_ptr); + + static Error + StringToFormat (const char *s, + lldb::Format &format, + size_t *byte_size_ptr); // If non-NULL, then a byte size can precede the format character + + static lldb::Encoding + StringToEncoding (const char *s, + lldb::Encoding fail_value = lldb::eEncodingInvalid); + + static uint32_t + StringToGenericRegister (const char *s); + + static const char * + StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update); + + static const char * + GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg); + + // EncodeEscapeSequences will change the textual representation of common + // escape sequences like "\n" (two characters) into a single '\n'. It does + // this for all of the supported escaped sequences and for the \0ooo (octal) + // and \xXX (hex). The resulting "dst" string will contain the character + // versions of all supported escape sequences. The common supported escape + // sequences are: "\a", "\b", "\f", "\n", "\r", "\t", "\v", "\'", "\"", "\\". + + static void + EncodeEscapeSequences (const char *src, std::string &dst); + + // ExpandEscapeSequences will change a string of possibly non-printable + // characters and expand them into text. So '\n' will turn into two chracters + // like "\n" which is suitable for human reading. When a character is not + // printable and isn't one of the common in escape sequences listed in the + // help for EncodeEscapeSequences, then it will be encoded as octal. Printable + // characters are left alone. + static void + ExpandEscapedCharacters (const char *src, std::string &dst); + + // This one isn't really relevant to Arguments per se, but we're using the Args as a + // general strings container, so... + void + LongestCommonPrefix (std::string &common_prefix); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from Args can see and modify these + //------------------------------------------------------------------ + typedef std::list<std::string> arg_sstr_collection; + typedef std::vector<const char *> arg_cstr_collection; + typedef std::vector<char> arg_quote_char_collection; + arg_sstr_collection m_args; + arg_cstr_collection m_argv; ///< The current argument vector. + arg_quote_char_collection m_args_quote_char; + + void + UpdateArgsAfterOptionParsing (); + + void + UpdateArgvFromArgs (); +}; + +} // namespace lldb_private + +#endif // liblldb_Command_h_ diff --git a/include/lldb/Interpreter/CommandCompletions.h b/include/lldb/Interpreter/CommandCompletions.h new file mode 100644 index 0000000..c4ab1b6 --- /dev/null +++ b/include/lldb/Interpreter/CommandCompletions.h @@ -0,0 +1,307 @@ +//===-- CommandCompletions.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_CommandCompletions_h_ +#define lldb_CommandCompletions_h_ + +// C Includes +// C++ Includes +#include <set> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/SearchFilter.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Core/RegularExpression.h" + +namespace lldb_private +{ +class CommandCompletions +{ +public: + + //---------------------------------------------------------------------- + // This is the command completion callback that is used to complete the argument of the option + // it is bound to (in the OptionDefinition table below). Return the total number of matches. + //---------------------------------------------------------------------- + typedef int (*CompletionCallback) (CommandInterpreter &interpreter, + const char *completion_str, // This is the argument we are completing + int match_start_point, // This is the point in the list of matches that you should start returning elements + int max_return_elements, // This is the number of matches requested. + lldb_private::SearchFilter *searcher,// A search filter to limit the search... + bool &word_complete, + lldb_private::StringList &matches); // The array of matches we return. + typedef enum + { + eNoCompletion = 0u, + eSourceFileCompletion = (1u << 0), + eDiskFileCompletion = (1u << 1), + eDiskDirectoryCompletion = (1u << 2), + eSymbolCompletion = (1u << 3), + eModuleCompletion = (1u << 4), + eSettingsNameCompletion = (1u << 5), + ePlatformPluginCompletion = (1u << 6), + eArchitectureCompletion = (1u << 7), + eVariablePathCompletion = (1u << 8), + // This item serves two purposes. It is the last element in the enum, + // so you can add custom enums starting from here in your Option class. + // Also if you & in this bit the base code will not process the option. + eCustomCompletion = (1u << 9) + + } CommonCompletionTypes; + + struct CommonCompletionElement + { + uint32_t type; + CompletionCallback callback; + }; + + static bool InvokeCommonCompletionCallbacks (CommandInterpreter &interpreter, + uint32_t completion_mask, + const char *completion_str, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + StringList &matches); + + //---------------------------------------------------------------------- + // These are the generic completer functions: + //---------------------------------------------------------------------- + static int + DiskFiles (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + StringList &matches); + static int + DiskDirectories (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + StringList &matches); + + static int + SourceFiles (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + StringList &matches); + + static int + Modules (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + lldb_private::StringList &matches); + + static int + Symbols (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + lldb_private::StringList &matches); + + static int + SettingsNames (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + lldb_private::StringList &matches); + + static int + PlatformPluginNames (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + lldb_private::StringList &matches); + + + static int + ArchitectureNames (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + lldb_private::StringList &matches); + + static int + VariablePath (CommandInterpreter &interpreter, + const char *partial_file_name, + int match_start_point, + int max_return_elements, + SearchFilter *searcher, + bool &word_complete, + lldb_private::StringList &matches); + + //---------------------------------------------------------------------- + // The Completer class is a convenient base class for building searchers + // that go along with the SearchFilter passed to the standard Completer + // functions. + //---------------------------------------------------------------------- + class Completer : public Searcher + { + public: + Completer (CommandInterpreter &interpreter, + const char *completion_str, + int match_start_point, + int max_return_elements, + StringList &matches); + + virtual ~Completer (); + + virtual CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete) = 0; + + virtual Depth + GetDepth () = 0; + + virtual size_t + DoCompletion (SearchFilter *filter) = 0; + + protected: + CommandInterpreter &m_interpreter; + std::string m_completion_str; + int m_match_start_point; + int m_max_return_elements; + StringList &m_matches; + private: + DISALLOW_COPY_AND_ASSIGN (Completer); + }; + + //---------------------------------------------------------------------- + // SouceFileCompleter implements the source file completer + //---------------------------------------------------------------------- + class SourceFileCompleter : public Completer + { + public: + + SourceFileCompleter (CommandInterpreter &interpreter, + bool include_support_files, + const char *completion_str, + int match_start_point, + int max_return_elements, + StringList &matches); + + virtual Searcher::Depth GetDepth (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete); + + size_t + DoCompletion (SearchFilter *filter); + + private: + bool m_include_support_files; + FileSpecList m_matching_files; + const char *m_file_name; + const char *m_dir_name; + DISALLOW_COPY_AND_ASSIGN (SourceFileCompleter); + + }; + + //---------------------------------------------------------------------- + // ModuleCompleter implements the module completer + //---------------------------------------------------------------------- + class ModuleCompleter : public Completer + { + public: + + ModuleCompleter (CommandInterpreter &interpreter, + const char *completion_str, + int match_start_point, + int max_return_elements, + StringList &matches); + + virtual Searcher::Depth GetDepth (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete); + + size_t + DoCompletion (SearchFilter *filter); + + private: + const char *m_file_name; + const char *m_dir_name; + DISALLOW_COPY_AND_ASSIGN (ModuleCompleter); + + }; + + //---------------------------------------------------------------------- + // SymbolCompleter implements the symbol completer + //---------------------------------------------------------------------- + class SymbolCompleter : public Completer + { + public: + + SymbolCompleter (CommandInterpreter &interpreter, + const char *completion_str, + int match_start_point, + int max_return_elements, + StringList &matches); + + virtual Searcher::Depth GetDepth (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool complete); + + size_t + DoCompletion (SearchFilter *filter); + + private: +// struct NameCmp { +// bool operator() (const ConstString& lhs, const ConstString& rhs) const +// { +// return lhs < rhs; +// } +// }; + + RegularExpression m_regex; + typedef std::set<ConstString> collection; + collection m_match_set; + DISALLOW_COPY_AND_ASSIGN (SymbolCompleter); + + }; + +private: + static CommonCompletionElement g_common_completions[]; + +}; + +} // namespace lldb_private +#endif // lldb_CommandCompletions_h_ diff --git a/include/lldb/Interpreter/CommandHistory.h b/include/lldb/Interpreter/CommandHistory.h new file mode 100644 index 0000000..dbe6e99 --- /dev/null +++ b/include/lldb/Interpreter/CommandHistory.h @@ -0,0 +1,76 @@ +//===-- CommandHistory.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_CommandHistory_h_ +#define liblldb_CommandHistory_h_ + +// C Includes +// C++ Includes +#include <string> +#include <vector> + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" +#include "lldb/Core/Stream.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class CommandHistory +{ +public: + CommandHistory (); + + ~CommandHistory (); + + size_t + GetSize () const; + + bool + IsEmpty () const; + + const char* + FindString (const char* input_str) const; + + const char* + GetStringAtIndex (size_t idx) const; + + const char* + operator [] (size_t idx) const; + + const char* + GetRecentmostString () const; + + void + AppendString (const std::string& str, + bool reject_if_dupe = true); + + void + Clear (); + + void + Dump (Stream& stream, + size_t start_idx = 0, + size_t stop_idx = SIZE_MAX) const; + + static const char g_repeat_char = '!'; + +private: + DISALLOW_COPY_AND_ASSIGN(CommandHistory); + + typedef std::vector<std::string> History; + mutable Mutex m_mutex; + History m_history; +}; + +} // namespace lldb_private + +#endif // liblldb_CommandHistory_h_ diff --git a/include/lldb/Interpreter/CommandInterpreter.h b/include/lldb/Interpreter/CommandInterpreter.h new file mode 100644 index 0000000..31fcc38 --- /dev/null +++ b/include/lldb/Interpreter/CommandInterpreter.h @@ -0,0 +1,486 @@ +//===-- CommandInterpreter.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_CommandInterpreter_h_ +#define liblldb_CommandInterpreter_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Log.h" +#include "lldb/Interpreter/CommandHistory.h" +#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Core/Event.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Core/StringList.h" + +namespace lldb_private { + +class CommandInterpreter : + public Broadcaster, + public Properties +{ +public: + typedef std::map<std::string, OptionArgVectorSP> OptionArgMap; + + enum + { + eBroadcastBitThreadShouldExit = (1 << 0), + eBroadcastBitResetPrompt = (1 << 1), + eBroadcastBitQuitCommandReceived = (1 << 2), // User entered quit + eBroadcastBitAsynchronousOutputData = (1 << 3), + eBroadcastBitAsynchronousErrorData = (1 << 4) + }; + + enum ChildrenTruncatedWarningStatus // tristate boolean to manage children truncation warning + { + eNoTruncation = 0, // never truncated + eUnwarnedTruncation = 1, // truncated but did not notify + eWarnedTruncation = 2 // truncated and notified + }; + + enum CommandTypes + { + eCommandTypesBuiltin = 0x0001, // native commands such as "frame" + eCommandTypesUserDef = 0x0002, // scripted commands + eCommandTypesAliases = 0x0004, // aliases such as "po" + eCommandTypesAllThem = 0xFFFF // all commands + }; + + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + + void + SourceInitFile (bool in_cwd, + CommandReturnObject &result); + + CommandInterpreter (Debugger &debugger, + lldb::ScriptLanguage script_language, + bool synchronous_execution); + + virtual + ~CommandInterpreter (); + + bool + AddCommand (const char *name, + const lldb::CommandObjectSP &cmd_sp, + bool can_replace); + + bool + AddUserCommand (std::string name, + const lldb::CommandObjectSP &cmd_sp, + bool can_replace); + + lldb::CommandObjectSP + GetCommandSPExact (const char *cmd, + bool include_aliases); + + CommandObject * + GetCommandObjectExact (const char *cmd_cstr, + bool include_aliases); + + CommandObject * + GetCommandObject (const char *cmd, + StringList *matches = NULL); + + bool + CommandExists (const char *cmd); + + bool + AliasExists (const char *cmd); + + bool + UserCommandExists (const char *cmd); + + void + AddAlias (const char *alias_name, + lldb::CommandObjectSP& command_obj_sp); + + bool + RemoveAlias (const char *alias_name); + + bool + GetAliasFullName (const char *cmd, std::string &full_name); + + bool + RemoveUser (const char *alias_name); + + void + RemoveAllUser () + { + m_user_dict.clear(); + } + + OptionArgVectorSP + GetAliasOptions (const char *alias_name); + + + bool + ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, + const char *options_args, + OptionArgVectorSP &option_arg_vector_sp); + + void + RemoveAliasOptions (const char *alias_name); + + void + AddOrReplaceAliasOptions (const char *alias_name, + OptionArgVectorSP &option_arg_vector_sp); + + CommandObject * + BuildAliasResult (const char *alias_name, + std::string &raw_input_string, + std::string &alias_result, + CommandReturnObject &result); + + bool + HandleCommand (const char *command_line, + LazyBool add_to_history, + CommandReturnObject &result, + ExecutionContext *override_context = NULL, + bool repeat_on_empty_command = true, + bool no_context_switching = false); + + //------------------------------------------------------------------ + /// Execute a list of commands in sequence. + /// + /// @param[in] commands + /// The list of commands to execute. + /// @param[in/out] context + /// The execution context in which to run the commands. Can be NULL in which case the default + /// context will be used. + /// @param[in] stop_on_continue + /// If \b true execution will end on the first command that causes the process in the + /// execution context to continue. If \false, we won't check the execution status. + /// @param[in] stop_on_error + /// If \b true execution will end on the first command that causes an error. + /// @param[in] echo_commands + /// If \b true echo the command before executing it. If \false, execute silently. + /// @param[in] print_results + /// If \b true print the results of the command after executing it. If \false, execute silently. + /// @param[out] result + /// This is marked as succeeding with no output if all commands execute safely, + /// and failed with some explanation if we aborted executing the commands at some point. + //------------------------------------------------------------------ + void + HandleCommands (const StringList &commands, + ExecutionContext *context, + bool stop_on_continue, + bool stop_on_error, + bool echo_commands, + bool print_results, + LazyBool add_to_history, + CommandReturnObject &result); + + //------------------------------------------------------------------ + /// Execute a list of commands from a file. + /// + /// @param[in] file + /// The file from which to read in commands. + /// @param[in/out] context + /// The execution context in which to run the commands. Can be NULL in which case the default + /// context will be used. + /// @param[in] stop_on_continue + /// If \b true execution will end on the first command that causes the process in the + /// execution context to continue. If \false, we won't check the execution status. + /// @param[in] stop_on_error + /// If \b true execution will end on the first command that causes an error. + /// @param[in] echo_commands + /// If \b true echo the command before executing it. If \false, execute silently. + /// @param[in] print_results + /// If \b true print the results of the command after executing it. If \false, execute silently. + /// @param[out] result + /// This is marked as succeeding with no output if all commands execute safely, + /// and failed with some explanation if we aborted executing the commands at some point. + //------------------------------------------------------------------ + void + HandleCommandsFromFile (FileSpec &file, + ExecutionContext *context, + bool stop_on_continue, + bool stop_on_error, + bool echo_commands, + bool print_results, + LazyBool add_to_history, + CommandReturnObject &result); + + CommandObject * + GetCommandObjectForCommand (std::string &command_line); + + // This handles command line completion. You are given a pointer to the command string buffer, to the current cursor, + // and to the end of the string (in case it is not NULL terminated). + // You also passed in an StringList object to fill with the returns. + // The first element of the array will be filled with the string that you would need to insert at + // the cursor point to complete the cursor point to the longest common matching prefix. + // If you want to limit the number of elements returned, set max_return_elements to the number of elements + // you want returned. Otherwise set max_return_elements to -1. + // If you want to start some way into the match list, then set match_start_point to the desired start + // point. + // Returns: + // -1 if the completion character should be inserted + // -2 if the entire command line should be deleted and replaced with matches.GetStringAtIndex(0) + // INT_MAX if the number of matches is > max_return_elements, but it is expensive to compute. + // Otherwise, returns the number of matches. + // + // FIXME: Only max_return_elements == -1 is supported at present. + + int + HandleCompletion (const char *current_line, + const char *cursor, + const char *last_char, + int match_start_point, + int max_return_elements, + StringList &matches); + + // This version just returns matches, and doesn't compute the substring. It is here so the + // Help command can call it for the first argument. + // word_complete tells whether a the completions are considered a "complete" response (so the + // completer should complete the quote & put a space after the word. + + int + HandleCompletionMatches (Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + + int + GetCommandNamesMatchingPartialString (const char *cmd_cstr, + bool include_aliases, + StringList &matches); + + void + GetHelp (CommandReturnObject &result, + uint32_t types = eCommandTypesAllThem); + + void + GetAliasHelp (const char *alias_name, + const char *command_name, + StreamString &help_string); + + void + OutputFormattedHelpText (Stream &stream, + const char *command_word, + const char *separator, + const char *help_text, + size_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 () + { + return m_debugger; + } + + ExecutionContext + GetExecutionContext() + { + return m_exe_ctx_ref.Lock(); + } + + void + UpdateExecutionContext (ExecutionContext *override_context); + + lldb::PlatformSP + GetPlatform (bool prefer_target_platform); + + const char * + ProcessEmbeddedScriptCommands (const char *arg); + + const char * + GetPrompt (); + + void + SetPrompt (const char *); + + bool Confirm (const char *message, bool default_answer); + + static size_t + GetConfirmationInputReaderCallback (void *baton, + InputReader &reader, + lldb::InputReaderAction action, + const char *bytes, + size_t bytes_len); + + void + LoadCommandDictionary (); + + void + Initialize (); + + void + SetScriptLanguage (lldb::ScriptLanguage lang); + + + bool + HasCommands (); + + bool + HasAliases (); + + bool + HasUserCommands (); + + bool + HasAliasOptions (); + + void + BuildAliasCommandArgs (CommandObject *alias_cmd_obj, + const char *alias_name, + Args &cmd_args, + std::string &raw_input_string, + CommandReturnObject &result); + + int + GetOptionArgumentPosition (const char *in_string); + + ScriptInterpreter * + GetScriptInterpreter (bool can_create = true); + + void + SkipLLDBInitFiles (bool skip_lldbinit_files) + { + m_skip_lldbinit_files = skip_lldbinit_files; + } + + void + SkipAppInitFiles (bool skip_app_init_files) + { + m_skip_app_init_files = m_skip_lldbinit_files; + } + + bool + GetSynchronous (); + + size_t + FindLongestCommandWord (CommandObject::CommandMap &dict); + + void + FindCommandsForApropos (const char *word, + StringList &commands_found, + StringList &commands_help, + bool search_builtin_commands, + bool search_user_commands); + + bool + GetBatchCommandMode () { return m_batch_command_mode; } + + void + SetBatchCommandMode (bool value) { m_batch_command_mode = value; } + + void + ChildrenTruncated () + { + if (m_truncation_warning == eNoTruncation) + m_truncation_warning = eUnwarnedTruncation; + } + + bool + TruncationWarningNecessary () + { + return (m_truncation_warning == eUnwarnedTruncation); + } + + void + TruncationWarningGiven () + { + m_truncation_warning = eWarnedTruncation; + } + + const char * + TruncationWarningText () + { + return "*** Some of your variables have more members than the debugger will show by default. To show all of them, you can either use the --show-all-children option to %s or raise the limit by changing the target.max-children-count setting.\n"; + } + + const CommandHistory& + GetCommandHistory () const + { + return m_command_history; + } + + CommandHistory& + GetCommandHistory () + { + return m_command_history; + } + + //------------------------------------------------------------------ + // Properties + //------------------------------------------------------------------ + bool + GetExpandRegexAliases () const; + + bool + GetPromptOnQuit () const; + + bool + GetStopCmdSourceOnError () const; + +protected: + friend class Debugger; + + void + SetSynchronous (bool value); + + lldb::CommandObjectSP + GetCommandSP (const char *cmd, bool include_aliases = true, bool exact = true, StringList *matches = NULL); + +private: + + Error + PreprocessCommand (std::string &command); + + Debugger &m_debugger; // The debugger session that this interpreter is associated with + ExecutionContextRef m_exe_ctx_ref; // The current execution context to use when handling commands + bool m_synchronous_execution; + bool m_skip_lldbinit_files; + bool m_skip_app_init_files; + CommandObject::CommandMap m_command_dict; // Stores basic built-in commands (they cannot be deleted, removed or overwritten). + CommandObject::CommandMap m_alias_dict; // Stores user aliases/abbreviations for commands + CommandObject::CommandMap m_user_dict; // Stores user-defined commands + OptionArgMap m_alias_options; // Stores any options (with or without arguments) that go with any alias. + CommandHistory m_command_history; + std::string m_repeat_command; // Stores the command that will be executed for an empty command string. + std::unique_ptr<ScriptInterpreter> m_script_interpreter_ap; + char m_comment_char; + bool m_batch_command_mode; + ChildrenTruncatedWarningStatus m_truncation_warning; // Whether we truncated children and whether the user has been told + uint32_t m_command_source_depth; + +}; + + +} // namespace lldb_private + +#endif // liblldb_CommandInterpreter_h_ diff --git a/include/lldb/Interpreter/CommandObject.h b/include/lldb/Interpreter/CommandObject.h new file mode 100644 index 0000000..2bfab0a --- /dev/null +++ b/include/lldb/Interpreter/CommandObject.h @@ -0,0 +1,608 @@ +//===-- CommandObject.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_CommandObject_h_ +#define liblldb_CommandObject_h_ + +#include <map> +#include <set> +#include <string> +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Core/StringList.h" +#include "lldb/Core/Flags.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +class CommandObject +{ +public: + + typedef const char *(ArgumentHelpCallbackFunction) (); + + struct ArgumentHelpCallback + { + 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 + { + lldb::CommandArgumentType arg_type; + const char *arg_name; + CommandCompletions::CommonCompletionTypes completion_type; + ArgumentHelpCallback help_function; + const char *help_text; + }; + + struct CommandArgumentData // Used to build individual command argument lists + { + lldb::CommandArgumentType arg_type; + ArgumentRepetitionType arg_repetition; + uint32_t arg_opt_set_association; // This arg might be associated only with some particular option set(s). + CommandArgumentData(): + arg_type(lldb::eArgTypeNone), + arg_repetition(eArgRepeatPlain), + arg_opt_set_association(LLDB_OPT_SET_ALL) // By default, the arg associates to all option sets. + {} + }; + + typedef std::vector<CommandArgumentData> CommandArgumentEntry; // Used to build individual command argument lists + + static ArgumentTableEntry g_arguments_data[lldb::eArgTypeLastArg]; // Main argument information table + + typedef std::map<std::string, lldb::CommandObjectSP> CommandMap; + + CommandObject (CommandInterpreter &interpreter, + const char *name, + const char *help = NULL, + const char *syntax = NULL, + uint32_t flags = 0); + + virtual + ~CommandObject (); + + + static const char * + GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type); + + static const char * + GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type); + + CommandInterpreter & + GetCommandInterpreter () + { + return m_interpreter; + } + + const char * + GetHelp (); + + virtual const char * + GetHelpLong (); + + const char * + GetSyntax (); + + const char * + GetCommandName (); + + void + SetHelp (const char * str); + + void + SetHelpLong (const char * str); + + void + SetHelpLong (std::string str); + + void + SetSyntax (const char *str); + + // override this to return true if you want to enable the user to delete + // the Command object from the Command dictionary (aliases have their own + // deletion scheme, so they do not need to care about this) + virtual bool + IsRemovable () const { return false; } + + bool + IsAlias () { return m_is_alias; } + + void + SetIsAlias (bool value) { m_is_alias = value; } + + virtual bool + IsMultiwordObject () { return false; } + + virtual lldb::CommandObjectSP + GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL) + { + return lldb::CommandObjectSP(); + } + + virtual CommandObject * + GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL) + { + return NULL; + } + + virtual void + AproposAllSubCommands (const char *prefix, + const char *search_word, + StringList &commands_found, + StringList &commands_help) + { + } + + void + GenerateHelpText (CommandReturnObject &result); + + virtual void + GenerateHelpText (Stream &result); + + // this is needed in order to allow the SBCommand class to + // transparently try and load subcommands - it will fail on + // anything but a multiword command, but it avoids us doing + // type checkings and casts + virtual bool + LoadSubCommand (const char *cmd_name, + const lldb::CommandObjectSP& command_obj) + { + return false; + } + + virtual bool + WantsRawCommandString() = 0; + + // By default, WantsCompletion = !WantsRawCommandString. + // Subclasses who want raw command string but desire, for example, + // argument completion should override this method to return true. + virtual bool + WantsCompletion() { return !WantsRawCommandString(); } + + virtual Options * + GetOptions (); + + static const ArgumentTableEntry* + GetArgumentTable (); + + static lldb::CommandArgumentType + LookupArgumentName (const char *arg_name); + + static ArgumentTableEntry * + FindArgumentDataByType (lldb::CommandArgumentType arg_type); + + int + GetNumArgumentEntries (); + + CommandArgumentEntry * + GetArgumentEntryAtIndex (int idx); + + static void + GetArgumentHelp (Stream &str, lldb::CommandArgumentType arg_type, CommandInterpreter &interpreter); + + static const char * + GetArgumentName (lldb::CommandArgumentType arg_type); + + // Generates a nicely formatted command args string for help command output. + // By default, all possible args are taken into account, for example, + // '<expr | variable-name>'. This can be refined by passing a second arg + // specifying which option set(s) we are interested, which could then, for + // example, produce either '<expr>' or '<variable-name>'. + void + GetFormattedCommandArguments (Stream &str, uint32_t opt_set_mask = LLDB_OPT_SET_ALL); + + bool + IsPairType (ArgumentRepetitionType arg_repeat_type); + + enum + { + //---------------------------------------------------------------------- + // eFlagRequiresTarget + // + // Ensures a valid target is contained in m_exe_ctx prior to executing + // the command. If a target doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidTargetDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidTargetDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eFlagRequiresTarget = (1u << 0), + //---------------------------------------------------------------------- + // eFlagRequiresProcess + // + // Ensures a valid process is contained in m_exe_ctx prior to executing + // the command. If a process doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidProcessDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidProcessDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eFlagRequiresProcess = (1u << 1), + //---------------------------------------------------------------------- + // eFlagRequiresThread + // + // Ensures a valid thread is contained in m_exe_ctx prior to executing + // the command. If a thread doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidThreadDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidThreadDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eFlagRequiresThread = (1u << 2), + //---------------------------------------------------------------------- + // eFlagRequiresFrame + // + // Ensures a valid frame is contained in m_exe_ctx prior to executing + // the command. If a frame doesn't exist or is invalid, the command + // will fail and CommandObject::GetInvalidFrameDescription() will be + // returned as the error. CommandObject subclasses can override the + // virtual function for GetInvalidFrameDescription() to provide custom + // strings when needed. + //---------------------------------------------------------------------- + eFlagRequiresFrame = (1u << 3), + //---------------------------------------------------------------------- + // eFlagRequiresRegContext + // + // Ensures a valid register context (from the selected frame if there + // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx) + // is availble from m_exe_ctx prior to executing the command. If a + // target doesn't exist or is invalid, the command will fail and + // CommandObject::GetInvalidRegContextDescription() will be returned as + // the error. CommandObject subclasses can override the virtual function + // for GetInvalidRegContextDescription() to provide custom strings when + // needed. + //---------------------------------------------------------------------- + eFlagRequiresRegContext = (1u << 4), + //---------------------------------------------------------------------- + // eFlagTryTargetAPILock + // + // Attempts to acquire the target lock if a target is selected in the + // command interpreter. If the command object fails to acquire the API + // lock, the command will fail with an appropriate error message. + //---------------------------------------------------------------------- + eFlagTryTargetAPILock = (1u << 5), + //---------------------------------------------------------------------- + // eFlagProcessMustBeLaunched + // + // Verifies that there is a launched process in m_exe_ctx, if there + // isn't, the command will fail with an appropriate error message. + //---------------------------------------------------------------------- + eFlagProcessMustBeLaunched = (1u << 6), + //---------------------------------------------------------------------- + // eFlagProcessMustBePaused + // + // Verifies that there is a paused process in m_exe_ctx, if there + // isn't, the command will fail with an appropriate error message. + //---------------------------------------------------------------------- + eFlagProcessMustBePaused = (1u << 7) + }; + + bool + ParseOptions (Args& args, CommandReturnObject &result); + + void + SetCommandName (const char *name); + + // This function really deals with CommandObjectLists, but we didn't make a + // CommandObjectList class, so I'm sticking it here. But we really should have + // such a class. Anyway, it looks up the commands in the map that match the partial + // string cmd_str, inserts the matches into matches, and returns the number added. + + static int + AddNamesMatchingPartialString (CommandMap &in_map, const char *cmd_str, StringList &matches); + + //------------------------------------------------------------------ + /// The input array contains a parsed version of the line. The insertion + /// point is given by cursor_index (the index in input of the word containing + /// the cursor) and cursor_char_position (the position of the cursor in that word.) + /// This default version handles calling option argument completions and then calls + /// HandleArgumentCompletion if the cursor is on an argument, not an option. + /// Don't override this method, override HandleArgumentCompletion instead unless + /// you have special reasons. + /// + /// @param[in] interpreter + /// The command interpreter doing the completion. + /// + /// @param[in] input + /// The command line parsed into words + /// + /// @param[in] cursor_index + /// The index in \ainput of the word in which the cursor lies. + /// + /// @param[in] cursor_char_pos + /// The character position of the cursor in its argument word. + /// + /// @param[in] match_start_point + /// @param[in] match_return_elements + /// FIXME: Not yet implemented... If there is a match that is expensive to compute, these are + /// here to allow you to compute the completions in batches. Start the completion from \amatch_start_point, + /// and return \amatch_return_elements elements. + /// + /// @param[out] word_complete + /// \btrue if this is a complete option value (a space will be inserted after the + /// completion.) \bfalse otherwise. + /// + /// @param[out] matches + /// The array of matches returned. + /// + /// FIXME: This is the wrong return value, since we also need to make a distinction between + /// total number of matches, and the window the user wants returned. + /// + /// @return + /// \btrue if we were in an option, \bfalse otherwise. + //------------------------------------------------------------------ + virtual int + HandleCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + //------------------------------------------------------------------ + /// The input array contains a parsed version of the line. The insertion + /// point is given by cursor_index (the index in input of the word containing + /// the cursor) and cursor_char_position (the position of the cursor in that word.) + /// We've constructed the map of options and their arguments as well if that is + /// helpful for the completion. + /// + /// @param[in] interpreter + /// The command interpreter doing the completion. + /// + /// @param[in] input + /// The command line parsed into words + /// + /// @param[in] cursor_index + /// The index in \ainput of the word in which the cursor lies. + /// + /// @param[in] cursor_char_pos + /// The character position of the cursor in its argument word. + /// + /// @param[in] opt_element_vector + /// The results of the options parse of \a input. + /// + /// @param[in] match_start_point + /// @param[in] match_return_elements + /// See CommandObject::HandleCompletions for a description of how these work. + /// + /// @param[out] word_complete + /// \btrue if this is a complete option value (a space will be inserted after the + /// completion.) \bfalse otherwise. + /// + /// @param[out] matches + /// The array of matches returned. + /// + /// FIXME: This is the wrong return value, since we also need to make a distinction between + /// total number of matches, and the window the user wants returned. + /// + /// @return + /// The number of completions. + //------------------------------------------------------------------ + + virtual int + HandleArgumentCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) + { + return 0; + } + + bool + HelpTextContainsWord (const char *search_word); + + //------------------------------------------------------------------ + /// The flags accessor. + /// + /// @return + /// A reference to the Flags member variable. + //------------------------------------------------------------------ + Flags& + GetFlags() + { + return m_flags; + } + + //------------------------------------------------------------------ + /// The flags const accessor. + /// + /// @return + /// A const reference to the Flags member variable. + //------------------------------------------------------------------ + const Flags& + GetFlags() const + { + return m_flags; + } + + //------------------------------------------------------------------ + /// Get the command that appropriate for a "repeat" of the current command. + /// + /// @param[in] current_command_line + /// The complete current command line. + /// + /// @return + /// NULL if there is no special repeat command - it will use the current command line. + /// Otherwise a pointer to the command to be repeated. + /// If the returned string is the empty string, the command won't be repeated. + //------------------------------------------------------------------ + virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) + { + return NULL; + } + + CommandOverrideCallback + GetOverrideCallback () const + { + return m_command_override_callback; + } + + void * + GetOverrideCallbackBaton () const + { + return m_command_override_baton; + } + + void + SetOverrideCallback (CommandOverrideCallback callback, void *baton) + { + m_command_override_callback = callback; + m_command_override_baton = baton; + } + + virtual bool + Execute (const char *args_string, CommandReturnObject &result) = 0; + +protected: + virtual const char * + GetInvalidTargetDescription() + { + return "invalid target, create a target using the 'target create' command"; + } + + virtual const char * + GetInvalidProcessDescription() + { + return "invalid process"; + } + + virtual const char * + GetInvalidThreadDescription() + { + return "invalid thread"; + } + + virtual const char * + GetInvalidFrameDescription() + { + return "invalid frame"; + } + + virtual const char * + GetInvalidRegContextDescription () + { + return "invalid frame, no registers"; + } + + //------------------------------------------------------------------ + /// Check the command to make sure anything required by this + /// command is available. + /// + /// @param[out] result + /// A command result object, if it is not okay to run the command + /// this will be filled in with a suitable error. + /// + /// @return + /// \b true if it is okay to run this command, \b false otherwise. + //------------------------------------------------------------------ + bool + CheckRequirements (CommandReturnObject &result); + + void + Cleanup (); + + CommandInterpreter &m_interpreter; + ExecutionContext m_exe_ctx; + Mutex::Locker m_api_locker; + std::string m_cmd_name; + std::string m_cmd_help_short; + std::string m_cmd_help_long; + std::string m_cmd_syntax; + bool m_is_alias; + Flags m_flags; + std::vector<CommandArgumentEntry> m_arguments; + CommandOverrideCallback m_command_override_callback; + void * m_command_override_baton; + + // Helper function to populate IDs or ID ranges as the command argument data + // to the specified command argument entry. + static void + AddIDsArgumentData(CommandArgumentEntry &arg, lldb::CommandArgumentType ID, lldb::CommandArgumentType IDRange); + +}; + +class CommandObjectParsed : public CommandObject +{ +public: + + CommandObjectParsed (CommandInterpreter &interpreter, + const char *name, + const char *help = NULL, + const char *syntax = NULL, + uint32_t flags = 0) : + CommandObject (interpreter, name, help, syntax, flags) {} + + virtual + ~CommandObjectParsed () {}; + + virtual bool + Execute (const char *args_string, CommandReturnObject &result); + +protected: + virtual bool + DoExecute (Args& command, + CommandReturnObject &result) = 0; + + virtual bool + WantsRawCommandString() { return false; }; +}; + +class CommandObjectRaw : public CommandObject +{ +public: + + CommandObjectRaw (CommandInterpreter &interpreter, + const char *name, + const char *help = NULL, + const char *syntax = NULL, + uint32_t flags = 0) : + CommandObject (interpreter, name, help, syntax, flags) {} + + virtual + ~CommandObjectRaw () {}; + + virtual bool + Execute (const char *args_string, CommandReturnObject &result); + +protected: + virtual bool + DoExecute (const char *command, CommandReturnObject &result) = 0; + + virtual bool + WantsRawCommandString() { return true; }; +}; + + +} // namespace lldb_private + + +#endif // liblldb_CommandObject_h_ diff --git a/include/lldb/Interpreter/CommandObjectMultiword.h b/include/lldb/Interpreter/CommandObjectMultiword.h new file mode 100644 index 0000000..491d43c --- /dev/null +++ b/include/lldb/Interpreter/CommandObjectMultiword.h @@ -0,0 +1,187 @@ +//===-- CommandObjectMultiword.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_CommandObjectMultiword_h_ +#define liblldb_CommandObjectMultiword_h_ + +// C Includes +// C++ Includes +#include <map> + +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/CommandObject.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// CommandObjectMultiword +//------------------------------------------------------------------------- + +class CommandObjectMultiword : public CommandObject +{ +// These two want to iterate over the subcommand dictionary. +friend class CommandInterpreter; +friend class CommandObjectSyntax; +public: + CommandObjectMultiword (CommandInterpreter &interpreter, + const char *name, + const char *help = NULL, + const char *syntax = NULL, + uint32_t flags = 0); + + virtual + ~CommandObjectMultiword (); + + virtual bool + IsMultiwordObject () { return true; } + + virtual bool + LoadSubCommand (const char *cmd_name, + const lldb::CommandObjectSP& command_obj); + + virtual void + GenerateHelpText (Stream &output_stream); + + virtual lldb::CommandObjectSP + GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL); + + virtual CommandObject * + GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL); + + virtual void + AproposAllSubCommands (const char *prefix, + const char *search_word, + StringList &commands_found, + StringList &commands_help); + + virtual bool + WantsRawCommandString() { return false; }; + + virtual int + HandleCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index); + + virtual bool + Execute (const char *args_string, + CommandReturnObject &result); + + virtual bool + IsRemovable() const { return m_can_be_removed; } + + void + SetRemovable (bool removable) + { + m_can_be_removed = removable; + } + +protected: + + CommandObject::CommandMap m_subcommand_dict; + bool m_can_be_removed; +}; + + +class CommandObjectProxy : public CommandObject +{ +public: + CommandObjectProxy (CommandInterpreter &interpreter, + const char *name, + const char *help = NULL, + const char *syntax = NULL, + uint32_t flags = 0); + + virtual + ~CommandObjectProxy (); + + // Subclasses must provide a command object that will be transparently + // used for this object. + virtual CommandObject * + GetProxyCommandObject() = 0; + + virtual const char * + GetHelpLong (); + + virtual bool + IsRemovable() const; + + virtual bool + IsMultiwordObject (); + + virtual lldb::CommandObjectSP + GetSubcommandSP (const char *sub_cmd, StringList *matches = NULL); + + virtual CommandObject * + GetSubcommandObject (const char *sub_cmd, StringList *matches = NULL); + + virtual void + AproposAllSubCommands (const char *prefix, + const char *search_word, + StringList &commands_found, + StringList &commands_help); + + virtual bool + LoadSubCommand (const char *cmd_name, + const lldb::CommandObjectSP& command_obj); + + virtual bool + WantsRawCommandString(); + + virtual bool + WantsCompletion(); + + virtual Options * + GetOptions (); + + + virtual int + HandleCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + virtual int + HandleArgumentCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + OptionElementVector &opt_element_vector, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + virtual const char * + GetRepeatCommand (Args ¤t_command_args, + uint32_t index); + + virtual bool + Execute (const char *args_string, + CommandReturnObject &result); + +protected: + + // These two want to iterate over the subcommand dictionary. + friend class CommandInterpreter; + friend class CommandObjectSyntax; + +}; + +} // namespace lldb_private + +#endif // liblldb_CommandObjectMultiword_h_ diff --git a/include/lldb/Interpreter/CommandObjectRegexCommand.h b/include/lldb/Interpreter/CommandObjectRegexCommand.h new file mode 100644 index 0000000..8855680 --- /dev/null +++ b/include/lldb/Interpreter/CommandObjectRegexCommand.h @@ -0,0 +1,81 @@ +//===-- CommandObjectRegexCommand.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_CommandObjectRegexCommand_h_ +#define liblldb_CommandObjectRegexCommand_h_ + +// C Includes +// C++ Includes +#include <list> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/RegularExpression.h" +#include "lldb/Interpreter/CommandObject.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// CommandObjectRegexCommand +//------------------------------------------------------------------------- + +class CommandObjectRegexCommand : public CommandObjectRaw +{ +public: + + CommandObjectRegexCommand (CommandInterpreter &interpreter, + const char *name, + const char *help, + const char *syntax, + uint32_t max_matches, + uint32_t completion_type_mask = 0); + + virtual + ~CommandObjectRegexCommand (); + + bool + AddRegexCommand (const char *re_cstr, const char *command_cstr); + + bool + HasRegexEntries () const + { + return !m_entries.empty(); + } + + virtual int + HandleCompletion (Args &input, + int &cursor_index, + int &cursor_char_position, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + +protected: + virtual bool + DoExecute (const char *command, CommandReturnObject &result); + + struct Entry + { + RegularExpression regex; + std::string command; + }; + + typedef std::list<Entry> EntryCollection; + const uint32_t m_max_matches; + const uint32_t m_completion_type_mask; + EntryCollection m_entries; + +private: + DISALLOW_COPY_AND_ASSIGN (CommandObjectRegexCommand); +}; + +} // namespace lldb_private + +#endif // liblldb_CommandObjectRegexCommand_h_ diff --git a/include/lldb/Interpreter/CommandReturnObject.h b/include/lldb/Interpreter/CommandReturnObject.h new file mode 100644 index 0000000..acd0399 --- /dev/null +++ b/include/lldb/Interpreter/CommandReturnObject.h @@ -0,0 +1,183 @@ +//===-- CommandReturnObject.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_CommandReturnObject_h_ +#define liblldb_CommandReturnObject_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/STLUtils.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/StreamTee.h" + +namespace lldb_private { + + +class CommandReturnObject +{ +public: + + CommandReturnObject (); + + ~CommandReturnObject (); + + const char * + GetOutputData () + { + lldb::StreamSP stream_sp (m_out_stream.GetStreamAtIndex (eStreamStringIndex)); + if (stream_sp) + return static_cast<StreamString *>(stream_sp.get())->GetData(); + return ""; + } + + const char * + GetErrorData () + { + lldb::StreamSP stream_sp (m_err_stream.GetStreamAtIndex (eStreamStringIndex)); + if (stream_sp) + return static_cast<StreamString *>(stream_sp.get())->GetData(); + else + return ""; + } + + Stream & + GetOutputStream () + { + // Make sure we at least have our normal string stream output stream + lldb::StreamSP stream_sp (m_out_stream.GetStreamAtIndex (eStreamStringIndex)); + if (!stream_sp) + { + stream_sp.reset (new StreamString()); + m_out_stream.SetStreamAtIndex (eStreamStringIndex, stream_sp); + } + return m_out_stream; + } + + Stream & + GetErrorStream () + { + // Make sure we at least have our normal string stream output stream + lldb::StreamSP stream_sp (m_err_stream.GetStreamAtIndex (eStreamStringIndex)); + if (!stream_sp) + { + stream_sp.reset (new StreamString()); + m_err_stream.SetStreamAtIndex (eStreamStringIndex, stream_sp); + } + return m_err_stream; + } + + void + SetImmediateOutputFile (FILE *fh, bool transfer_fh_ownership = false) + { + lldb::StreamSP stream_sp (new StreamFile (fh, transfer_fh_ownership)); + m_out_stream.SetStreamAtIndex (eImmediateStreamIndex, stream_sp); + } + + void + SetImmediateErrorFile (FILE *fh, bool transfer_fh_ownership = false) + { + lldb::StreamSP stream_sp (new StreamFile (fh, transfer_fh_ownership)); + m_err_stream.SetStreamAtIndex (eImmediateStreamIndex, stream_sp); + } + + void + SetImmediateOutputStream (const lldb::StreamSP &stream_sp) + { + m_out_stream.SetStreamAtIndex (eImmediateStreamIndex, stream_sp); + } + + void + SetImmediateErrorStream (const lldb::StreamSP &stream_sp) + { + m_err_stream.SetStreamAtIndex (eImmediateStreamIndex, stream_sp); + } + + lldb::StreamSP + GetImmediateOutputStream () + { + return m_out_stream.GetStreamAtIndex (eImmediateStreamIndex); + } + + lldb::StreamSP + GetImmediateErrorStream () + { + return m_err_stream.GetStreamAtIndex (eImmediateStreamIndex); + } + + void + Clear(); + + void + AppendMessage (const char *in_string); + + void + AppendMessageWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + void + AppendRawWarning (const char *in_string); + + void + AppendWarning (const char *in_string); + + void + AppendWarningWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + void + AppendError (const char *in_string); + + void + AppendRawError (const char *in_string); + + void + AppendErrorWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + + void + SetError (const Error &error, + const char *fallback_error_cstr = NULL); + + void + SetError (const char *error_cstr); + + lldb::ReturnStatus + GetStatus(); + + void + SetStatus (lldb::ReturnStatus status); + + bool + Succeeded (); + + bool + HasResult (); + + bool GetDidChangeProcessState (); + + void SetDidChangeProcessState (bool b); + +private: + enum + { + eStreamStringIndex = 0, + eImmediateStreamIndex = 1 + }; + + StreamTee m_out_stream; + StreamTee m_err_stream; + + lldb::ReturnStatus m_status; + bool m_did_change_process_state; +}; + +} // namespace lldb_private + +#endif // liblldb_CommandReturnObject_h_ diff --git a/include/lldb/Interpreter/OptionGroupArchitecture.h b/include/lldb/Interpreter/OptionGroupArchitecture.h new file mode 100644 index 0000000..7cd1ca3 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupArchitecture.h @@ -0,0 +1,73 @@ +//===-- OptionGroupArchitecture.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_OptionGroupArchitecture_h_ +#define liblldb_OptionGroupArchitecture_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Core/ArchSpec.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// OptionGroupArchitecture +//------------------------------------------------------------------------- + +class OptionGroupArchitecture : public OptionGroup +{ +public: + + OptionGroupArchitecture (); + + virtual + ~OptionGroupArchitecture (); + + + virtual uint32_t + GetNumDefinitions (); + + virtual const OptionDefinition* + GetDefinitions (); + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + bool + GetArchitecture (Platform *platform, ArchSpec &arch); + + bool + ArchitectureWasSpecified () const + { + return !m_arch_str.empty(); + } + const char * + GetArchitectureName () + { + if (m_arch_str.empty()) + return NULL; + return m_arch_str.c_str(); + } + +protected: + + std::string m_arch_str; // Save the arch triple in case a platform is specified after the architecture +}; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupArchitecture_h_ diff --git a/include/lldb/Interpreter/OptionGroupBoolean.h b/include/lldb/Interpreter/OptionGroupBoolean.h new file mode 100644 index 0000000..0d861b2 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupBoolean.h @@ -0,0 +1,83 @@ +//===-- OptionGroupBoolean.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_OptionGroupBoolean_h_ +#define liblldb_OptionGroupBoolean_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueBoolean.h" + +namespace lldb_private { + //------------------------------------------------------------------------- + // OptionGroupBoolean + //------------------------------------------------------------------------- + + class OptionGroupBoolean : public OptionGroup + { + public: + // When 'no_argument_toggle_default' is true, then setting the option + // value does NOT require an argument, it sets the boolean value to the + // inverse of the default value + OptionGroupBoolean (uint32_t usage_mask, + bool required, + const char *long_option, + int short_option, + const char *usage_text, + bool default_value, + bool no_argument_toggle_default); + + virtual + ~OptionGroupBoolean (); + + + 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); + + OptionValueBoolean & + GetOptionValue () + { + return m_value; + } + + const OptionValueBoolean & + GetOptionValue () const + { + return m_value; + } + + protected: + OptionValueBoolean m_value; + OptionDefinition m_option_definition; + + }; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupBoolean_h_ diff --git a/include/lldb/Interpreter/OptionGroupFile.h b/include/lldb/Interpreter/OptionGroupFile.h new file mode 100644 index 0000000..632a2db --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupFile.h @@ -0,0 +1,142 @@ +//===-- OptionGroupFile.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_OptionGroupFile_h_ +#define liblldb_OptionGroupFile_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueFileSpec.h" +#include "lldb/Interpreter/OptionValueFileSpecList.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// OptionGroupFile +//------------------------------------------------------------------------- + +class OptionGroupFile : public OptionGroup +{ +public: + + OptionGroupFile (uint32_t usage_mask, + bool required, + const char *long_option, + int short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text); + + virtual + ~OptionGroupFile (); + + + 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); + + OptionValueFileSpec & + GetOptionValue () + { + return m_file; + } + + const OptionValueFileSpec & + GetOptionValue () const + { + return m_file; + } + +protected: + OptionValueFileSpec m_file; + OptionDefinition m_option_definition; + +}; + +//------------------------------------------------------------------------- +// OptionGroupFileList +//------------------------------------------------------------------------- + +class OptionGroupFileList : public OptionGroup +{ +public: + + OptionGroupFileList (uint32_t usage_mask, + bool required, + const char *long_option, + int 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_ diff --git a/include/lldb/Interpreter/OptionGroupFormat.h b/include/lldb/Interpreter/OptionGroupFormat.h new file mode 100644 index 0000000..7419b04 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupFormat.h @@ -0,0 +1,133 @@ +//===-- OptionGroupFormat.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_OptionGroupFormat_h_ +#define liblldb_OptionGroupFormat_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueFormat.h" +#include "lldb/Interpreter/OptionValueSInt64.h" +#include "lldb/Interpreter/OptionValueUInt64.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// OptionGroupFormat +//------------------------------------------------------------------------- + +class OptionGroupFormat : public OptionGroup +{ +public: + static const uint32_t OPTION_GROUP_FORMAT = LLDB_OPT_SET_1; + static const uint32_t OPTION_GROUP_GDB_FMT = LLDB_OPT_SET_2; + static const uint32_t OPTION_GROUP_SIZE = LLDB_OPT_SET_3; + static const uint32_t OPTION_GROUP_COUNT = LLDB_OPT_SET_4; + + OptionGroupFormat (lldb::Format default_format, + uint64_t default_byte_size = UINT64_MAX, // Pass UINT64_MAX to disable the "--size" option + uint64_t default_count = UINT64_MAX); // Pass UINT64_MAX to disable the "--count" option + + virtual + ~OptionGroupFormat (); + + + virtual uint32_t + GetNumDefinitions (); + + virtual const OptionDefinition* + GetDefinitions (); + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + lldb::Format + GetFormat () const + { + return m_format.GetCurrentValue(); + } + + OptionValueFormat & + GetFormatValue() + { + return m_format; + } + + const OptionValueFormat & + GetFormatValue() const + { + return m_format; + } + + OptionValueUInt64 & + GetByteSizeValue() + { + return m_byte_size; + } + + const OptionValueUInt64 & + GetByteSizeValue() const + { + return m_byte_size; + } + + OptionValueUInt64 & + GetCountValue() + { + return m_count; + } + + const OptionValueUInt64 & + GetCountValue() const + { + return m_count; + } + + bool + HasGDBFormat () const + { + return m_has_gdb_format; + } + + bool + AnyOptionWasSet () const + { + return m_format.OptionWasSet() || + m_byte_size.OptionWasSet() || + m_count.OptionWasSet(); + } + +protected: + + bool + ParserGDBFormatLetter (CommandInterpreter &interpreter, + char format_letter, + lldb::Format &format, + uint32_t &byte_size); + + OptionValueFormat m_format; + OptionValueUInt64 m_byte_size; + OptionValueUInt64 m_count; + char m_prev_gdb_format; + char m_prev_gdb_size; + + bool m_has_gdb_format; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupFormat_h_ diff --git a/include/lldb/Interpreter/OptionGroupOutputFile.h b/include/lldb/Interpreter/OptionGroupOutputFile.h new file mode 100644 index 0000000..533cd6e --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupOutputFile.h @@ -0,0 +1,76 @@ +//===-- OptionGroupOutputFile.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_OptionGroupOutputFile_h_ +#define liblldb_OptionGroupOutputFile_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueBoolean.h" +#include "lldb/Interpreter/OptionValueFileSpec.h" + +namespace lldb_private { +//------------------------------------------------------------------------- +// OptionGroupOutputFile +//------------------------------------------------------------------------- + +class OptionGroupOutputFile : public OptionGroup +{ +public: + + OptionGroupOutputFile (); + + virtual + ~OptionGroupOutputFile (); + + + virtual uint32_t + GetNumDefinitions (); + + virtual const OptionDefinition* + GetDefinitions (); + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + const OptionValueFileSpec & + GetFile () + { + return m_file; + } + + const OptionValueBoolean & + GetAppend () + { + return m_append; + } + + bool + AnyOptionWasSet () const + { + return m_file.OptionWasSet() || m_append.OptionWasSet(); + } + +protected: + OptionValueFileSpec m_file; + OptionValueBoolean m_append; + +}; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupOutputFile_h_ diff --git a/include/lldb/Interpreter/OptionGroupPlatform.h b/include/lldb/Interpreter/OptionGroupPlatform.h new file mode 100644 index 0000000..970ad32 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupPlatform.h @@ -0,0 +1,120 @@ +//===-- OptionGroupPlatform.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_OptionGroupPlatform_h_ +#define liblldb_OptionGroupPlatform_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Interpreter/Options.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// PlatformOptionGroup +// +// Make platform options available to any commands that need the settings. +//------------------------------------------------------------------------- +class OptionGroupPlatform : public OptionGroup +{ +public: + + OptionGroupPlatform (bool include_platform_option) : + OptionGroup(), + m_platform_name (), + m_sdk_sysroot (), + m_os_version_major (UINT32_MAX), + m_os_version_minor (UINT32_MAX), + m_os_version_update (UINT32_MAX), + m_include_platform_option (include_platform_option) + { + } + + virtual + ~OptionGroupPlatform () + { + } + + virtual uint32_t + GetNumDefinitions (); + + virtual const OptionDefinition* + GetDefinitions (); + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + lldb::PlatformSP + CreatePlatformWithOptions (CommandInterpreter &interpreter, + const ArchSpec &arch, + bool make_selected, + Error& error, + ArchSpec &platform_arch) const; + + bool + PlatformWasSpecified () const + { + return !m_platform_name.empty(); + } + + void + SetPlatformName (const char *platform_name) + { + if (platform_name && platform_name[0]) + m_platform_name.assign (platform_name); + else + m_platform_name.clear(); + } + + const ConstString & + GetSDKRootDirectory () const + { + return m_sdk_sysroot; + } + + void + SetSDKRootDirectory (const ConstString &sdk_root_directory) + { + m_sdk_sysroot = sdk_root_directory; + } + + const ConstString & + GetSDKBuild () const + { + return m_sdk_build; + } + + void + SetSDKBuild (const ConstString &sdk_build) + { + m_sdk_build = sdk_build; + } + + +protected: + std::string m_platform_name; + ConstString m_sdk_sysroot; + ConstString m_sdk_build; + uint32_t m_os_version_major; + uint32_t m_os_version_minor; + uint32_t m_os_version_update; + bool m_include_platform_option; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupPlatform_h_ diff --git a/include/lldb/Interpreter/OptionGroupString.h b/include/lldb/Interpreter/OptionGroupString.h new file mode 100644 index 0000000..e62a81b --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupString.h @@ -0,0 +1,82 @@ +//===-- OptionGroupString.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_OptionGroupString_h_ +#define liblldb_OptionGroupString_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueString.h" + +namespace lldb_private { + //------------------------------------------------------------------------- + // OptionGroupString + //------------------------------------------------------------------------- + + class OptionGroupString : public OptionGroup + { + public: + + OptionGroupString (uint32_t usage_mask, + bool required, + const char *long_option, + int short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text, + const char *default_value); + + virtual + ~OptionGroupString (); + + + 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); + + OptionValueString & + GetOptionValue () + { + return m_value; + } + + const OptionValueString & + GetOptionValue () const + { + return m_value; + } + + protected: + OptionValueString m_value; + OptionDefinition m_option_definition; + + }; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupString_h_ diff --git a/include/lldb/Interpreter/OptionGroupUInt64.h b/include/lldb/Interpreter/OptionGroupUInt64.h new file mode 100644 index 0000000..c5f9e85 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupUInt64.h @@ -0,0 +1,82 @@ +//===-- OptionGroupUInt64.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_OptionGroupUInt64_h_ +#define liblldb_OptionGroupUInt64_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueUInt64.h" + +namespace lldb_private { + //------------------------------------------------------------------------- + // OptionGroupUInt64 + //------------------------------------------------------------------------- + + class OptionGroupUInt64 : public OptionGroup + { + public: + + OptionGroupUInt64 (uint32_t usage_mask, + bool required, + const char *long_option, + int short_option, + uint32_t completion_type, + lldb::CommandArgumentType argument_type, + const char *usage_text, + uint64_t default_value); + + virtual + ~OptionGroupUInt64 (); + + + 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); + + OptionValueUInt64 & + GetOptionValue () + { + return m_value; + } + + const OptionValueUInt64 & + GetOptionValue () const + { + return m_value; + } + + protected: + OptionValueUInt64 m_value; + OptionDefinition m_option_definition; + + }; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupUInt64_h_ diff --git a/include/lldb/Interpreter/OptionGroupUUID.h b/include/lldb/Interpreter/OptionGroupUUID.h new file mode 100644 index 0000000..ea968d7 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupUUID.h @@ -0,0 +1,61 @@ +//===-- OptionGroupUUID.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_OptionGroupUUID_h_ +#define liblldb_OptionGroupUUID_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" +#include "lldb/Interpreter/OptionValueUUID.h" + +namespace lldb_private { +//------------------------------------------------------------------------- +// OptionGroupUUID +//------------------------------------------------------------------------- + +class OptionGroupUUID : public OptionGroup +{ +public: + + OptionGroupUUID (); + + virtual + ~OptionGroupUUID (); + + + virtual uint32_t + GetNumDefinitions (); + + virtual const OptionDefinition* + GetDefinitions (); + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + const OptionValueUUID & + GetOptionValue () const + { + return m_uuid; + } + +protected: + OptionValueUUID m_uuid; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupUUID_h_ diff --git a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h new file mode 100644 index 0000000..da05e12 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h @@ -0,0 +1,85 @@ +//===-- OptionGroupValueObjectDisplay.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_OptionGroupValueObjectDisplay_h_ +#define liblldb_OptionGroupValueObjectDisplay_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ValueObject.h" +#include "lldb/Interpreter/Options.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// OptionGroupValueObjectDisplay +//------------------------------------------------------------------------- + +class OptionGroupValueObjectDisplay : public OptionGroup +{ +public: + + OptionGroupValueObjectDisplay (); + + virtual + ~OptionGroupValueObjectDisplay (); + + + virtual uint32_t + GetNumDefinitions (); + + virtual const OptionDefinition* + GetDefinitions (); + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value); + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter); + + bool + AnyOptionWasSet () const + { + return show_types == true || + no_summary_depth != 0 || + show_location == true || + flat_output == true || + use_objc == true || + max_depth != UINT32_MAX || + ptr_depth != 0 || + use_synth == false || + be_raw == true || + ignore_cap == true; + } + + ValueObject::DumpValueObjectOptions + GetAsDumpOptions (bool objc_is_compact = false, + lldb::Format format = lldb::eFormatDefault, + lldb::TypeSummaryImplSP summary_sp = lldb::TypeSummaryImplSP()); + + bool show_types; + uint32_t no_summary_depth; + bool show_location; + bool flat_output; + bool use_objc; + uint32_t max_depth; + uint32_t ptr_depth; + lldb::DynamicValueType use_dynamic; + bool use_synth; + bool be_raw; + bool ignore_cap; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupValueObjectDisplay_h_ diff --git a/include/lldb/Interpreter/OptionGroupVariable.h b/include/lldb/Interpreter/OptionGroupVariable.h new file mode 100644 index 0000000..40f4d43 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupVariable.h @@ -0,0 +1,65 @@ +//===-- 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/OptionValueString.h" +#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; + OptionValueString summary; // the name of a named summary + OptionValueString summary_string; // a summary string + + private: + DISALLOW_COPY_AND_ASSIGN(OptionGroupVariable); + }; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupVariable_h_ diff --git a/include/lldb/Interpreter/OptionGroupWatchpoint.h b/include/lldb/Interpreter/OptionGroupWatchpoint.h new file mode 100644 index 0000000..1298da8 --- /dev/null +++ b/include/lldb/Interpreter/OptionGroupWatchpoint.h @@ -0,0 +1,71 @@ +//===-- OptionGroupWatchpoint.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_OptionGroupWatchpoint_h_ +#define liblldb_OptionGroupWatchpoint_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/Options.h" + +namespace lldb_private { + +//------------------------------------------------------------------------- +// OptionGroupWatchpoint +//------------------------------------------------------------------------- + + class OptionGroupWatchpoint : public OptionGroup + { + public: + + static bool + IsWatchSizeSupported(uint32_t watch_size); + + OptionGroupWatchpoint (); + + virtual + ~OptionGroupWatchpoint (); + + 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); + + // Note: + // eWatchRead == LLDB_WATCH_TYPE_READ; and + // eWatchWrite == LLDB_WATCH_TYPE_WRITE + typedef enum WatchType { + eWatchInvalid = 0, + eWatchRead, + eWatchWrite, + eWatchReadWrite + } WatchType; + + WatchType watch_type; + uint32_t watch_size; + bool watch_type_specified; + + private: + DISALLOW_COPY_AND_ASSIGN(OptionGroupWatchpoint); + }; + +} // namespace lldb_private + +#endif // liblldb_OptionGroupWatchpoint_h_ diff --git a/include/lldb/Interpreter/OptionValue.h b/include/lldb/Interpreter/OptionValue.h new file mode 100644 index 0000000..33e7fc5 --- /dev/null +++ b/include/lldb/Interpreter/OptionValue.h @@ -0,0 +1,384 @@ +//===-- OptionValue.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_OptionValue_h_ +#define liblldb_OptionValue_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-defines.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" + +namespace lldb_private { + + //--------------------------------------------------------------------- + // OptionValue + //--------------------------------------------------------------------- + class OptionValue + { + public: + typedef enum { + eTypeInvalid = 0, + eTypeArch, + eTypeArgs, + eTypeArray, + eTypeBoolean, + eTypeDictionary, + eTypeEnum, + eTypeFileSpec, + eTypeFileSpecList, + eTypeFormat, + eTypePathMap, + eTypeProperties, + eTypeRegex, + eTypeSInt64, + eTypeString, + eTypeUInt64, + eTypeUUID + } Type; + + enum { + eDumpOptionName = (1u << 0), + eDumpOptionType = (1u << 1), + eDumpOptionValue = (1u << 2), + eDumpOptionDescription = (1u << 3), + eDumpOptionRaw = (1u << 4), + eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue), + eDumpGroupHelp = (eDumpOptionName | eDumpOptionType | eDumpOptionDescription) + }; + + + OptionValue () : + m_value_was_set (false) + { + } + + OptionValue (const OptionValue &rhs) : + m_value_was_set (rhs.m_value_was_set) + { + } + + virtual ~OptionValue () + { + } + //----------------------------------------------------------------- + // Subclasses should override these functions + //----------------------------------------------------------------- + virtual Type + GetType () const = 0; + + // If this value is always hidden, the avoid showing any info on this + // value, just show the info for the child values. + virtual bool + ValueIsTransparent () const + { + return GetType() == eTypeProperties; + } + + virtual const char * + GetTypeAsCString () const + { + return GetBuiltinTypeAsCString(GetType()); + } + + + static const char * + GetBuiltinTypeAsCString (Type t); + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) = 0; + + virtual Error + SetValueFromCString (const char *value, VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () = 0; + + virtual lldb::OptionValueSP + DeepCopy () const = 0; + + virtual size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + //----------------------------------------------------------------- + // Subclasses can override these functions + //----------------------------------------------------------------- + virtual lldb::OptionValueSP + GetSubValue (const ExecutionContext *exe_ctx, + const char *name, + bool will_modify, + Error &error) const + { + error.SetErrorStringWithFormat("'%s' is not a value subvalue", name); + return lldb::OptionValueSP(); + } + + virtual Error + SetSubValue (const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *name, + const char *value); + + virtual bool + IsAggregateValue () const + { + return false; + } + + virtual ConstString + GetName() const + { + return ConstString(); + } + + virtual bool + DumpQualifiedName (Stream &strm) const; + //----------------------------------------------------------------- + // Subclasses should NOT override these functions as they use the + // above functions to implement functionality + //----------------------------------------------------------------- + uint32_t + GetTypeAsMask () + { + return 1u << GetType(); + } + + static uint32_t + ConvertTypeToMask (OptionValue::Type type) + { + return 1u << type; + } + + static OptionValue::Type + ConvertTypeMaskToType (uint32_t type_mask) + { + // If only one bit is set, then return an appropriate enumeration + switch (type_mask) + { + case 1u << eTypeArch: return eTypeArch; + case 1u << eTypeArgs: return eTypeArgs; + case 1u << eTypeArray: return eTypeArray; + case 1u << eTypeBoolean: return eTypeBoolean; + case 1u << eTypeDictionary: return eTypeDictionary; + case 1u << eTypeEnum: return eTypeEnum; + case 1u << eTypeFileSpec: return eTypeFileSpec; + case 1u << eTypeFileSpecList: return eTypeFileSpecList; + case 1u << eTypeFormat: return eTypeFormat; + case 1u << eTypePathMap: return eTypePathMap; + case 1u << eTypeProperties: return eTypeProperties; + case 1u << eTypeRegex: return eTypeRegex; + case 1u << eTypeSInt64: return eTypeSInt64; + case 1u << eTypeString: return eTypeString; + case 1u << eTypeUInt64: return eTypeUInt64; + case 1u << eTypeUUID: return eTypeUUID; + } + // Else return invalid + return eTypeInvalid; + } + + static lldb::OptionValueSP + CreateValueFromCStringForTypeMask (const char *value_cstr, + uint32_t type_mask, + Error &error); + + // Get this value as a uint64_t value if it is encoded as a boolean, + // uint64_t or int64_t. Other types will cause "fail_value" to be + // returned + uint64_t + GetUInt64Value (uint64_t fail_value, bool *success_ptr); + + OptionValueArch * + GetAsArch (); + + const OptionValueArch * + GetAsArch () const; + + OptionValueArray * + GetAsArray (); + + const OptionValueArray * + GetAsArray () const; + + OptionValueArgs * + GetAsArgs (); + + const OptionValueArgs * + GetAsArgs () const; + + OptionValueBoolean * + GetAsBoolean (); + + const OptionValueBoolean * + GetAsBoolean () const; + + OptionValueDictionary * + GetAsDictionary (); + + const OptionValueDictionary * + GetAsDictionary () const; + + OptionValueEnumeration * + GetAsEnumeration (); + + const OptionValueEnumeration * + GetAsEnumeration () const; + + OptionValueFileSpec * + GetAsFileSpec (); + + const OptionValueFileSpec * + GetAsFileSpec () const; + + OptionValueFileSpecList * + GetAsFileSpecList (); + + const OptionValueFileSpecList * + GetAsFileSpecList () const; + + OptionValueFormat * + GetAsFormat (); + + const OptionValueFormat * + GetAsFormat () const; + + OptionValuePathMappings * + GetAsPathMappings (); + + const OptionValuePathMappings * + GetAsPathMappings () const; + + OptionValueProperties * + GetAsProperties (); + + const OptionValueProperties * + GetAsProperties () const; + + OptionValueRegex * + GetAsRegex (); + + const OptionValueRegex * + GetAsRegex () const; + + OptionValueSInt64 * + GetAsSInt64 (); + + const OptionValueSInt64 * + GetAsSInt64 () const; + + OptionValueString * + GetAsString (); + + const OptionValueString * + GetAsString () const; + + OptionValueUInt64 * + GetAsUInt64 (); + + const OptionValueUInt64 * + GetAsUInt64 () const; + + OptionValueUUID * + GetAsUUID (); + + const OptionValueUUID * + GetAsUUID () const; + + bool + GetBooleanValue (bool fail_value = false) const; + + bool + SetBooleanValue (bool new_value); + + int64_t + GetEnumerationValue (int64_t fail_value = -1) const; + + bool + SetEnumerationValue (int64_t value); + + FileSpec + GetFileSpecValue () const; + + bool + SetFileSpecValue (const FileSpec &file_spec); + + FileSpecList + GetFileSpecListValue () const; + + lldb::Format + GetFormatValue (lldb::Format fail_value = lldb::eFormatDefault) const; + + bool + SetFormatValue (lldb::Format new_value); + + const RegularExpression * + GetRegexValue () const; + + int64_t + GetSInt64Value (int64_t fail_value = 0) const; + + bool + SetSInt64Value (int64_t new_value); + + const char * + GetStringValue (const char *fail_value = NULL) const; + + bool + SetStringValue (const char *new_value); + + uint64_t + GetUInt64Value (uint64_t fail_value = 0) const; + + bool + SetUInt64Value (uint64_t new_value); + + UUID + GetUUIDValue () const; + + bool + SetUUIDValue (const UUID &uuid); + + bool + OptionWasSet () const + { + return m_value_was_set; + } + + void + SetOptionWasSet () + { + m_value_was_set = true; + } + + void + SetParent (const lldb::OptionValueSP &parent_sp) + { + m_parent_wp = parent_sp; + } + protected: + lldb::OptionValueWP m_parent_wp; + bool m_value_was_set; // This can be used to see if a value has been set + // by a call to SetValueFromCString(). It is often + // handy to know if an option value was set from + // the command line or as a setting, versus if we + // just have the default value that was already + // populated in the option value. + + }; + +} // namespace lldb_private + +#endif // liblldb_OptionValue_h_ diff --git a/include/lldb/Interpreter/OptionValueArch.h b/include/lldb/Interpreter/OptionValueArch.h new file mode 100644 index 0000000..662e1ec --- /dev/null +++ b/include/lldb/Interpreter/OptionValueArch.h @@ -0,0 +1,139 @@ +//===-- OptionValueArch.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_OptionValueArch_h_ +#define liblldb_OptionValueArch_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ArchSpec.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueArch : public OptionValue +{ +public: + OptionValueArch () : + OptionValue(), + m_current_value (), + m_default_value () + { + } + + OptionValueArch (const char *triple) : + OptionValue(), + m_current_value (triple), + m_default_value () + { + m_default_value = m_current_value; + } + + OptionValueArch (const ArchSpec &value) : + OptionValue(), + m_current_value (value), + m_default_value (value) + { + } + + OptionValueArch (const ArchSpec ¤t_value, + const ArchSpec &default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value) + { + } + + virtual + ~OptionValueArch() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeArch; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + ArchSpec & + GetCurrentValue() + { + return m_current_value; + } + + const ArchSpec & + GetCurrentValue() const + { + return m_current_value; + } + + const ArchSpec & + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (const ArchSpec &value, bool set_value_was_set) + { + m_current_value = value; + if (set_value_was_set) + m_value_was_set = true; + } + + void + SetDefaultValue (const ArchSpec &value) + { + m_default_value = value; + } + +protected: + ArchSpec m_current_value; + ArchSpec m_default_value; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueArch_h_ diff --git a/include/lldb/Interpreter/OptionValueArgs.h b/include/lldb/Interpreter/OptionValueArgs.h new file mode 100644 index 0000000..365a52a --- /dev/null +++ b/include/lldb/Interpreter/OptionValueArgs.h @@ -0,0 +1,46 @@ +//===-- OptionValueArgs.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_OptionValueArgs_h_ +#define liblldb_OptionValueArgs_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValueArray.h" + +namespace lldb_private { + +class OptionValueArgs : public OptionValueArray +{ +public: + OptionValueArgs () : + OptionValueArray (OptionValue::ConvertTypeToMask (OptionValue::eTypeString)) + { + } + + virtual + ~OptionValueArgs() + { + } + + size_t + GetArgs (Args &args); + + virtual Type + GetType() const + { + return eTypeArgs; + } +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueArgs_h_ diff --git a/include/lldb/Interpreter/OptionValueArray.h b/include/lldb/Interpreter/OptionValueArray.h new file mode 100644 index 0000000..39ae2f6 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueArray.h @@ -0,0 +1,178 @@ +//===-- OptionValueArray.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_OptionValueArray_h_ +#define liblldb_OptionValueArray_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueArray : public OptionValue +{ +public: + OptionValueArray (uint32_t type_mask = UINT32_MAX, bool raw_value_dump = false) : + m_type_mask (type_mask), + m_values (), + m_raw_value_dump(raw_value_dump) + { + } + + virtual + ~OptionValueArray() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeArray; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_values.clear(); + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual bool + IsAggregateValue () const + { + return true; + } + + virtual lldb::OptionValueSP + GetSubValue (const ExecutionContext *exe_ctx, + const char *name, + bool will_modify, + Error &error) const; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + size_t + GetSize () const + { + return m_values.size(); + } + + lldb::OptionValueSP + operator[](size_t idx) const + { + lldb::OptionValueSP value_sp; + if (idx < m_values.size()) + value_sp = m_values[idx]; + return value_sp; + } + + lldb::OptionValueSP + GetValueAtIndex (size_t idx) const + { + lldb::OptionValueSP value_sp; + if (idx < m_values.size()) + value_sp = m_values[idx]; + return value_sp; + } + + bool + AppendValue (const lldb::OptionValueSP &value_sp) + { + // Make sure the value_sp object is allowed to contain + // values of the type passed in... + if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) + { + m_values.push_back(value_sp); + return true; + } + return false; + } + + bool + InsertValue (size_t idx, const lldb::OptionValueSP &value_sp) + { + // Make sure the value_sp object is allowed to contain + // values of the type passed in... + if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) + { + if (idx < m_values.size()) + m_values.insert(m_values.begin() + idx, value_sp); + else + m_values.push_back(value_sp); + return true; + } + return false; + } + + bool + ReplaceValue (size_t idx, const lldb::OptionValueSP &value_sp) + { + // Make sure the value_sp object is allowed to contain + // values of the type passed in... + if (value_sp && (m_type_mask & value_sp->GetTypeAsMask())) + { + if (idx < m_values.size()) + { + m_values[idx] = value_sp; + return true; + } + } + return false; + } + + bool + DeleteValue (size_t idx) + { + if (idx < m_values.size()) + { + m_values.erase (m_values.begin() + idx); + return true; + } + return false; + } + + size_t + GetArgs (Args &args) const; + + Error + SetArgs (const Args &args, VarSetOperationType op); + +protected: + typedef std::vector<lldb::OptionValueSP> collection; + + uint32_t m_type_mask; + collection m_values; + bool m_raw_value_dump; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueArray_h_ diff --git a/include/lldb/Interpreter/OptionValueBoolean.h b/include/lldb/Interpreter/OptionValueBoolean.h new file mode 100644 index 0000000..2b935e9 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueBoolean.h @@ -0,0 +1,141 @@ +//===-- OptionValueBoolean.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_OptionValueBoolean_h_ +#define liblldb_OptionValueBoolean_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueBoolean : public OptionValue +{ +public: + OptionValueBoolean (bool value) : + OptionValue(), + m_current_value (value), + m_default_value (value) + { + } + OptionValueBoolean (bool current_value, + bool default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value) + { + } + + virtual + ~OptionValueBoolean() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeBoolean; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + virtual size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + //------------------------------------------------------------------ + /// Convert to bool operator. + /// + /// This allows code to check a OptionValueBoolean in conditions. + /// + /// @code + /// OptionValueBoolean bool_value(...); + /// if (bool_value) + /// { ... + /// @endcode + /// + /// @return + /// /b True this object contains a valid namespace decl, \b + /// false otherwise. + //------------------------------------------------------------------ + operator bool() const + { + return m_current_value; + } + + const bool & + operator = (bool b) + { + m_current_value = b; + return m_current_value; + } + + bool + GetCurrentValue() const + { + return m_current_value; + } + + bool + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (bool value) + { + m_current_value = value; + } + + void + SetDefaultValue (bool value) + { + m_default_value = value; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + +protected: + bool m_current_value; + bool m_default_value; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueBoolean_h_ diff --git a/include/lldb/Interpreter/OptionValueDictionary.h b/include/lldb/Interpreter/OptionValueDictionary.h new file mode 100644 index 0000000..5fb698b --- /dev/null +++ b/include/lldb/Interpreter/OptionValueDictionary.h @@ -0,0 +1,139 @@ +//===-- OptionValueDictionary.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_OptionValueDictionary_h_ +#define liblldb_OptionValueDictionary_h_ + +// C Includes +// C++ Includes +#include <map> + +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueDictionary : public OptionValue +{ +public: + OptionValueDictionary (uint32_t type_mask = UINT32_MAX, bool raw_value_dump = true) : + OptionValue(), + m_type_mask (type_mask), + m_values (), + m_raw_value_dump (raw_value_dump) + { + } + + virtual + ~OptionValueDictionary() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeDictionary; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_values.clear(); + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual bool + IsAggregateValue () const + { + return true; + } + + bool + IsHomogenous() const + { + return ConvertTypeMaskToType (m_type_mask) != eTypeInvalid; + } + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + size_t + GetNumValues() const + { + return m_values.size(); + } + + lldb::OptionValueSP + GetValueForKey (const ConstString &key) const; + + virtual lldb::OptionValueSP + GetSubValue (const ExecutionContext *exe_ctx, + const char *name, + bool will_modify, + Error &error) const; + + virtual Error + SetSubValue (const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *name, + const char *value); + + //--------------------------------------------------------------------- + // String value getters and setters + //--------------------------------------------------------------------- + const char * + GetStringValueForKey (const ConstString &key); + + bool + SetStringValueForKey (const ConstString &key, + const char *value, + bool can_replace = true); + + + bool + SetValueForKey (const ConstString &key, + const lldb::OptionValueSP &value_sp, + bool can_replace = true); + + bool + DeleteValueForKey (const ConstString &key); + + size_t + GetArgs (Args &args) const; + + Error + SetArgs (const Args &args, VarSetOperationType op); + +protected: + typedef std::map<ConstString, lldb::OptionValueSP> collection; + uint32_t m_type_mask; + collection m_values; + bool m_raw_value_dump; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueDictionary_h_ diff --git a/include/lldb/Interpreter/OptionValueEnumeration.h b/include/lldb/Interpreter/OptionValueEnumeration.h new file mode 100644 index 0000000..012eeb6 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueEnumeration.h @@ -0,0 +1,126 @@ +//===-- OptionValueEnumeration.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_OptionValueEnumeration_h_ +#define liblldb_OptionValueEnumeration_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + + +class OptionValueEnumeration : public OptionValue +{ +public: + typedef int64_t enum_type; + struct EnumeratorInfo + { + enum_type value; + const char *description; + }; + typedef UniqueCStringMap<EnumeratorInfo> EnumerationMap; + typedef typename EnumerationMap::Entry EnumerationMapEntry; + + OptionValueEnumeration (const OptionEnumValueElement *enumerators, enum_type value); + + virtual + ~OptionValueEnumeration(); + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeEnum; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + enum_type + operator = (enum_type value) + { + m_current_value = value; + return m_current_value; + } + + enum_type + GetCurrentValue() const + { + return m_current_value; + } + + enum_type + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (enum_type value) + { + m_current_value = value; + } + + void + SetDefaultValue (enum_type value) + { + m_default_value = value; + } + +protected: + void + SetEnumerations (const OptionEnumValueElement *enumerators); + + enum_type m_current_value; + enum_type m_default_value; + EnumerationMap m_enumerations; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueEnumeration_h_ diff --git a/include/lldb/Interpreter/OptionValueFileSpec.h b/include/lldb/Interpreter/OptionValueFileSpec.h new file mode 100644 index 0000000..7e74b60 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueFileSpec.h @@ -0,0 +1,129 @@ +//===-- OptionValueFileSpec.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_OptionValueFileSpec_h_ +#define liblldb_OptionValueFileSpec_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Host/FileSpec.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueFileSpec : public OptionValue +{ +public: + OptionValueFileSpec (); + + OptionValueFileSpec (const FileSpec &value); + + OptionValueFileSpec (const FileSpec ¤t_value, + const FileSpec &default_value); + + virtual + ~OptionValueFileSpec() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeFileSpec; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + m_data_sp.reset(); + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + FileSpec & + GetCurrentValue() + { + return m_current_value; + } + + const FileSpec & + GetCurrentValue() const + { + return m_current_value; + } + + const FileSpec & + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (const FileSpec &value, bool set_value_was_set) + { + m_current_value = value; + if (set_value_was_set) + m_value_was_set = true; + m_data_sp.reset(); + } + + void + SetDefaultValue (const FileSpec &value) + { + m_default_value = value; + } + + const lldb::DataBufferSP & + GetFileContents(bool null_terminate); + + void + SetCompletionMask (uint32_t mask) + { + m_completion_mask = mask; + } + +protected: + FileSpec m_current_value; + FileSpec m_default_value; + lldb::DataBufferSP m_data_sp; + uint32_t m_completion_mask; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueFileSpec_h_ diff --git a/include/lldb/Interpreter/OptionValueFileSpecList.h b/include/lldb/Interpreter/OptionValueFileSpecList.h new file mode 100644 index 0000000..792de4e --- /dev/null +++ b/include/lldb/Interpreter/OptionValueFileSpecList.h @@ -0,0 +1,105 @@ +//===-- OptionValueFileSpecList.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_OptionValueFileSpecList_h_ +#define liblldb_OptionValueFileSpecList_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/FileSpecList.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueFileSpecList : public OptionValue +{ +public: + OptionValueFileSpecList () : + OptionValue(), + m_current_value () + { + } + + OptionValueFileSpecList (const FileSpecList ¤t_value) : + OptionValue(), + m_current_value (current_value) + { + } + + + virtual + ~OptionValueFileSpecList() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeFileSpecList; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value.Clear(); + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual bool + IsAggregateValue () const + { + 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; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueFileSpecList_h_ diff --git a/include/lldb/Interpreter/OptionValueFormat.h b/include/lldb/Interpreter/OptionValueFormat.h new file mode 100644 index 0000000..245b2ee --- /dev/null +++ b/include/lldb/Interpreter/OptionValueFormat.h @@ -0,0 +1,107 @@ +//===-- OptionValueFormat.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_OptionValueFormat_h_ +#define liblldb_OptionValueFormat_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueFormat : public OptionValue +{ +public: + OptionValueFormat (lldb::Format value) : + OptionValue(), + m_current_value (value), + m_default_value (value) + { + } + + OptionValueFormat (lldb::Format current_value, + lldb::Format default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value) + { + } + + virtual + ~OptionValueFormat() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeFormat; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + lldb::Format + GetCurrentValue() const + { + return m_current_value; + } + + lldb::Format + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (lldb::Format value) + { + m_current_value = value; + } + + void + SetDefaultValue (lldb::Format value) + { + m_default_value = value; + } + +protected: + lldb::Format m_current_value; + lldb::Format m_default_value; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueFormat_h_ diff --git a/include/lldb/Interpreter/OptionValuePathMappings.h b/include/lldb/Interpreter/OptionValuePathMappings.h new file mode 100644 index 0000000..7ebf494 --- /dev/null +++ b/include/lldb/Interpreter/OptionValuePathMappings.h @@ -0,0 +1,94 @@ +//===-- OptionValuePathMappings.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_OptionValuePathMappings_h_ +#define liblldb_OptionValuePathMappings_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/PathMappingList.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValuePathMappings : public OptionValue +{ +public: + OptionValuePathMappings (bool notify_changes) : + OptionValue(), + m_path_mappings (), + m_notify_changes (notify_changes) + { + } + + virtual + ~OptionValuePathMappings() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypePathMap; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_path_mappings.Clear(m_notify_changes); + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual bool + IsAggregateValue () const + { + return true; + } + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + PathMappingList & + GetCurrentValue() + { + return m_path_mappings; + } + + const PathMappingList & + GetCurrentValue() const + { + return m_path_mappings; + } + +protected: + PathMappingList m_path_mappings; + bool m_notify_changes; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValuePathMappings_h_ diff --git a/include/lldb/Interpreter/OptionValueProperties.h b/include/lldb/Interpreter/OptionValueProperties.h new file mode 100644 index 0000000..0024f20 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueProperties.h @@ -0,0 +1,265 @@ +//===-- OptionValueProperties.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_OptionValueProperties_h_ +#define liblldb_OptionValueProperties_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Interpreter/OptionValue.h" +#include "lldb/Interpreter/Property.h" + +namespace lldb_private { + +class OptionValueProperties : + public OptionValue, + public std::enable_shared_from_this<OptionValueProperties> +{ +public: + + //--------------------------------------------------------------------- + // OptionValueProperties + //--------------------------------------------------------------------- + OptionValueProperties () : + OptionValue(), + m_name (), + m_properties (), + m_name_to_index () + { + } + + OptionValueProperties (const ConstString &name); + + OptionValueProperties (const OptionValueProperties &global_properties); + + virtual + ~OptionValueProperties() + { + } + + virtual Type + GetType () const + { + return eTypeProperties; + } + + virtual bool + Clear (); + + virtual lldb::OptionValueSP + DeepCopy () const; + + virtual Error + SetValueFromCString (const char *value, VarSetOperationType op = eVarSetOperationAssign); + + virtual void + DumpValue (const ExecutionContext *exe_ctx, + Stream &strm, + uint32_t dump_mask); + + virtual ConstString + GetName () const + { + return m_name; + } + + virtual Error + DumpPropertyValue (const ExecutionContext *exe_ctx, + Stream &strm, + const char *property_path, + uint32_t dump_mask); + + virtual void + DumpAllDescriptions (CommandInterpreter &interpreter, + Stream &strm) const; + + void + Apropos (const char *keyword, + std::vector<const Property *> &matching_properties) const; + + void + Initialize (const PropertyDefinition *setting_definitions); + +// bool +// GetQualifiedName (Stream &strm); + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + virtual size_t + GetNumProperties() const; + + virtual ConstString + GetPropertyNameAtIndex (uint32_t idx) const; + + virtual const char * + GetPropertyDescriptionAtIndex (uint32_t idx) const; + + //--------------------------------------------------------------------- + // Get the index of a property given its exact name in this property + // collection, "name" can't be a path to a property path that refers + // to a property within a property + //--------------------------------------------------------------------- + virtual uint32_t + GetPropertyIndex (const ConstString &name) const; + + //--------------------------------------------------------------------- + // Get a property by exact name exists in this property collection, name + // can not be a path to a property path that refers to a property within + // a property + //--------------------------------------------------------------------- + virtual const Property * + GetProperty (const ExecutionContext *exe_ctx, + bool will_modify, + const ConstString &name) const; + + virtual const Property * + GetPropertyAtIndex (const ExecutionContext *exe_ctx, + bool will_modify, + uint32_t idx) const; + + //--------------------------------------------------------------------- + // Property can be be a property path like "target.process.extra-startup-command" + //--------------------------------------------------------------------- + virtual const Property * + GetPropertyAtPath (const ExecutionContext *exe_ctx, + bool will_modify, + const char *property_path) const; + + virtual lldb::OptionValueSP + GetPropertyValueAtIndex (const ExecutionContext *exe_ctx, + bool will_modify, + uint32_t idx) const; + + virtual lldb::OptionValueSP + GetValueForKey (const ExecutionContext *exe_ctx, + const ConstString &key, + bool value_will_be_modified) const; + + lldb::OptionValueSP + GetSubValue (const ExecutionContext *exe_ctx, + const char *name, + bool value_will_be_modified, + Error &error) const; + + virtual Error + SetSubValue (const ExecutionContext *exe_ctx, + VarSetOperationType op, + const char *path, + const char *value); + + virtual bool + PredicateMatches (const ExecutionContext *exe_ctx, + const char *predicate) const + { + return false; + } + + + OptionValueArch * + GetPropertyAtIndexAsOptionValueArch (const ExecutionContext *exe_ctx, uint32_t idx) const; + + bool + GetPropertyAtIndexAsArgs (const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const; + + bool + SetPropertyAtIndexFromArgs (const ExecutionContext *exe_ctx, uint32_t idx, const Args &args); + + bool + GetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool fail_value) const; + + bool + SetPropertyAtIndexAsBoolean (const ExecutionContext *exe_ctx, uint32_t idx, bool new_value); + + OptionValueDictionary * + GetPropertyAtIndexAsOptionValueDictionary (const ExecutionContext *exe_ctx, uint32_t idx) const; + + int64_t + GetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const; + + bool + SetPropertyAtIndexAsEnumeration (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value); + + const RegularExpression * + GetPropertyAtIndexAsOptionValueRegex (const ExecutionContext *exe_ctx, uint32_t idx) const; + + OptionValueSInt64 * + GetPropertyAtIndexAsOptionValueSInt64 (const ExecutionContext *exe_ctx, uint32_t idx) const; + + int64_t + GetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t fail_value) const; + + bool + SetPropertyAtIndexAsSInt64 (const ExecutionContext *exe_ctx, uint32_t idx, int64_t new_value); + + uint64_t + GetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t fail_value) const; + + bool + SetPropertyAtIndexAsUInt64 (const ExecutionContext *exe_ctx, uint32_t idx, uint64_t new_value); + + const char * + GetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *fail_value) const; + + bool + SetPropertyAtIndexAsString (const ExecutionContext *exe_ctx, uint32_t idx, const char *new_value); + + OptionValueString * + GetPropertyAtIndexAsOptionValueString (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const; + + OptionValueFileSpec * + GetPropertyAtIndexAsOptionValueFileSpec (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const; + + FileSpec + GetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx) const; + + bool + SetPropertyAtIndexAsFileSpec (const ExecutionContext *exe_ctx, uint32_t idx, const FileSpec &file_spec); + + OptionValuePathMappings * + GetPropertyAtIndexAsOptionValuePathMappings (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const; + + OptionValueFileSpecList * + GetPropertyAtIndexAsOptionValueFileSpecList (const ExecutionContext *exe_ctx, bool will_modify, uint32_t idx) const; + + void + AppendProperty(const ConstString &name, + const ConstString &desc, + bool is_global, + const lldb::OptionValueSP &value_sp); + + lldb::OptionValuePropertiesSP + GetSubProperty (const ExecutionContext *exe_ctx, + const ConstString &name); + +protected: + + const Property * + ProtectedGetPropertyAtIndex (uint32_t idx) const + { + if (idx < m_properties.size()) + return &m_properties[idx]; + return NULL; + } + + typedef UniqueCStringMap<size_t> NameToIndex; + + ConstString m_name; + std::vector<Property> m_properties; + NameToIndex m_name_to_index; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueProperties_h_ diff --git a/include/lldb/Interpreter/OptionValueRegex.h b/include/lldb/Interpreter/OptionValueRegex.h new file mode 100644 index 0000000..bb8c458 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueRegex.h @@ -0,0 +1,98 @@ +//===-- OptionValueRegex.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_OptionValueRegex_h_ +#define liblldb_OptionValueRegex_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/RegularExpression.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueRegex : public OptionValue +{ +public: + OptionValueRegex (const char *value = NULL, uint32_t regex_flags = 0) : + OptionValue(), + m_regex (value, regex_flags) + { + } + + virtual + ~OptionValueRegex() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeRegex; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_regex.Clear(); + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + const RegularExpression * + GetCurrentValue() const + { + if (m_regex.IsValid()) + return &m_regex; + return NULL; + } + + void + SetCurrentValue (const char *value, uint32_t regex_flags) + { + if (value && value[0]) + m_regex.Compile (value, regex_flags); + else + m_regex.Clear(); + } + + bool + IsValid () const + { + return m_regex.IsValid(); + } + +protected: + RegularExpression m_regex; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueRegex_h_ diff --git a/include/lldb/Interpreter/OptionValueSInt64.h b/include/lldb/Interpreter/OptionValueSInt64.h new file mode 100644 index 0000000..8bc8fb2 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueSInt64.h @@ -0,0 +1,172 @@ +//===-- OptionValueSInt64.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_OptionValueSInt64_h_ +#define liblldb_OptionValueSInt64_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueSInt64 : public OptionValue +{ +public: + OptionValueSInt64 () : + OptionValue(), + m_current_value (0), + m_default_value (0), + m_min_value (INT64_MIN), + m_max_value (INT64_MAX) + { + } + + OptionValueSInt64 (int64_t value) : + OptionValue(), + m_current_value (value), + m_default_value (value), + m_min_value (INT64_MIN), + m_max_value (INT64_MAX) + { + } + + OptionValueSInt64 (int64_t current_value, + int64_t default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value), + m_min_value (INT64_MIN), + m_max_value (INT64_MAX) + { + } + + OptionValueSInt64 (const OptionValueSInt64 &rhs) : + OptionValue(rhs), + m_current_value (rhs.m_current_value), + m_default_value (rhs.m_default_value), + m_min_value (rhs.m_min_value), + m_max_value (rhs.m_max_value) + { + } + + virtual + ~OptionValueSInt64() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeSInt64; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + const int64_t & + operator = (int64_t value) + { + m_current_value = value; + return m_current_value; + } + + int64_t + GetCurrentValue() const + { + return m_current_value; + } + + int64_t + GetDefaultValue() const + { + return m_default_value; + } + + bool + SetCurrentValue (int64_t value) + { + if (value >= m_min_value && value <= m_max_value) + { + m_current_value = value; + return true; + } + return false; + } + + bool + SetDefaultValue (int64_t value) + { + if (value >= m_min_value && value <= m_max_value) + { + m_default_value = value; + return true; + } + return false; + } + + void + SetMinimumValue (int64_t v) + { + m_min_value = v; + } + + int64_t + GetMinimumValue () const + { + return m_min_value; + } + + void + SetMaximumValue (int64_t v) + { + m_max_value = v; + } + + int64_t + GetMaximumValue () const + { + return m_max_value; + } + +protected: + int64_t m_current_value; + int64_t m_default_value; + int64_t m_min_value; + int64_t m_max_value; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueSInt64_h_ diff --git a/include/lldb/Interpreter/OptionValueString.h b/include/lldb/Interpreter/OptionValueString.h new file mode 100644 index 0000000..a82e140 --- /dev/null +++ b/include/lldb/Interpreter/OptionValueString.h @@ -0,0 +1,227 @@ +//===-- OptionValueString.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_OptionValueString_h_ +#define liblldb_OptionValueString_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Flags.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueString : public OptionValue +{ +public: + + typedef Error (*ValidatorCallback) (const char* string, + void* baton); + + enum Options + { + eOptionEncodeCharacterEscapeSequences = (1u << 0) + }; + + OptionValueString () : + OptionValue(), + m_current_value (), + m_default_value (), + m_options(), + m_validator(), + m_validator_baton() + { + } + + OptionValueString (ValidatorCallback validator, + void* baton = NULL) : + OptionValue(), + m_current_value (), + m_default_value (), + m_options(), + m_validator(validator), + m_validator_baton(baton) + { + } + + OptionValueString (const char *value) : + OptionValue(), + m_current_value (), + m_default_value (), + m_options(), + m_validator(), + m_validator_baton() + { + if (value && value[0]) + { + m_current_value.assign (value); + m_default_value.assign (value); + } + } + + OptionValueString (const char *current_value, + const char *default_value) : + OptionValue(), + m_current_value (), + m_default_value (), + m_options(), + m_validator(), + m_validator_baton() + { + if (current_value && current_value[0]) + m_current_value.assign (current_value); + if (default_value && default_value[0]) + m_default_value.assign (default_value); + } + + OptionValueString (const char *value, + ValidatorCallback validator, + void* baton = NULL) : + OptionValue(), + m_current_value (), + m_default_value (), + m_options(), + m_validator(validator), + m_validator_baton(baton) + { + if (value && value[0]) + { + m_current_value.assign (value); + m_default_value.assign (value); + } + } + + OptionValueString (const char *current_value, + const char *default_value, + ValidatorCallback validator, + void* baton = NULL) : + OptionValue(), + m_current_value (), + m_default_value (), + m_options(), + m_validator(validator), + m_validator_baton(baton) + { + if (current_value && current_value[0]) + m_current_value.assign (current_value); + if (default_value && default_value[0]) + m_default_value.assign (default_value); + } + + virtual + ~OptionValueString() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeString; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + Flags & + GetOptions () + { + return m_options; + } + + const Flags & + GetOptions () const + { + return m_options; + } + + const char * + operator = (const char *value) + { + SetCurrentValue(value); + return m_current_value.c_str(); + } + + const char * + GetCurrentValue() const + { + return m_current_value.c_str(); + } + + const char * + GetDefaultValue() const + { + return m_default_value.c_str(); + } + + Error + SetCurrentValue (const char *value); + + Error + AppendToCurrentValue (const char *value); + + void + SetDefaultValue (const char *value) + { + if (value && value[0]) + m_default_value.assign (value); + else + m_default_value.clear(); + } + + bool + IsCurrentValueEmpty () const + { + return m_current_value.empty(); + } + + bool + IsDefaultValueEmpty () const + { + return m_default_value.empty(); + } + + +protected: + std::string m_current_value; + std::string m_default_value; + Flags m_options; + ValidatorCallback m_validator; + void* m_validator_baton; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueString_h_ diff --git a/include/lldb/Interpreter/OptionValueUInt64.h b/include/lldb/Interpreter/OptionValueUInt64.h new file mode 100644 index 0000000..9b5496f --- /dev/null +++ b/include/lldb/Interpreter/OptionValueUInt64.h @@ -0,0 +1,134 @@ +//===-- OptionValueUInt64.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_OptionValueUInt64_h_ +#define liblldb_OptionValueUInt64_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueUInt64 : public OptionValue +{ +public: + OptionValueUInt64 () : + OptionValue(), + m_current_value (0), + m_default_value (0) + { + } + + OptionValueUInt64 (uint64_t value) : + OptionValue(), + m_current_value (value), + m_default_value (value) + { + } + + OptionValueUInt64 (uint64_t current_value, + uint64_t default_value) : + OptionValue(), + m_current_value (current_value), + m_default_value (default_value) + { + } + + virtual + ~OptionValueUInt64() + { + } + + //--------------------------------------------------------------------- + // Decode a uint64_t from "value_cstr" return a OptionValueUInt64 object + // inside of a lldb::OptionValueSP object if all goes well. If the + // string isn't a uint64_t value or any other error occurs, return an + // empty lldb::OptionValueSP and fill error in with the correct stuff. + //--------------------------------------------------------------------- + static lldb::OptionValueSP + Create (const char *value_cstr, Error &error); + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeUInt64; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_current_value = m_default_value; + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + const uint64_t & + operator = (uint64_t value) + { + m_current_value = value; + return m_current_value; + } + + operator uint64_t () const + { + return m_current_value; + } + + uint64_t + GetCurrentValue() const + { + return m_current_value; + } + + uint64_t + GetDefaultValue() const + { + return m_default_value; + } + + void + SetCurrentValue (uint64_t value) + { + m_current_value = value; + } + + void + SetDefaultValue (uint64_t value) + { + m_default_value = value; + } + +protected: + uint64_t m_current_value; + uint64_t m_default_value; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueUInt64_h_ diff --git a/include/lldb/Interpreter/OptionValueUUID.h b/include/lldb/Interpreter/OptionValueUUID.h new file mode 100644 index 0000000..caf436e --- /dev/null +++ b/include/lldb/Interpreter/OptionValueUUID.h @@ -0,0 +1,106 @@ +//===-- OptionValueUUID.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_OptionValueUUID_h_ +#define liblldb_OptionValueUUID_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/UUID.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + +class OptionValueUUID : public OptionValue +{ +public: + OptionValueUUID () : + OptionValue(), + m_uuid () + { + } + + OptionValueUUID (const UUID &uuid) : + OptionValue(), + m_uuid (uuid) + { + } + + virtual + ~OptionValueUUID() + { + } + + //--------------------------------------------------------------------- + // Virtual subclass pure virtual overrides + //--------------------------------------------------------------------- + + virtual OptionValue::Type + GetType () const + { + return eTypeUUID; + } + + virtual void + DumpValue (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask); + + virtual Error + SetValueFromCString (const char *value, + VarSetOperationType op = eVarSetOperationAssign); + + virtual bool + Clear () + { + m_uuid.Clear(); + m_value_was_set = false; + return true; + } + + virtual lldb::OptionValueSP + DeepCopy () const; + + //--------------------------------------------------------------------- + // Subclass specific functions + //--------------------------------------------------------------------- + + UUID & + GetCurrentValue() + { + return m_uuid; + } + + const UUID & + GetCurrentValue() const + { + return m_uuid; + } + + void + SetCurrentValue (const UUID &value) + { + m_uuid = value; + } + + virtual size_t + AutoComplete (CommandInterpreter &interpreter, + const char *s, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + +protected: + UUID m_uuid; +}; + +} // namespace lldb_private + +#endif // liblldb_OptionValueUUID_h_ diff --git a/include/lldb/Interpreter/OptionValues.h b/include/lldb/Interpreter/OptionValues.h new file mode 100644 index 0000000..41b9d2e --- /dev/null +++ b/include/lldb/Interpreter/OptionValues.h @@ -0,0 +1,31 @@ +//===-- OptionValues.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_OptionValues_h_ +#define liblldb_OptionValues_h_ + +#include "lldb/Interpreter/OptionValue.h" +#include "lldb/Interpreter/OptionValueArch.h" +#include "lldb/Interpreter/OptionValueArgs.h" +#include "lldb/Interpreter/OptionValueArray.h" +#include "lldb/Interpreter/OptionValueBoolean.h" +#include "lldb/Interpreter/OptionValueDictionary.h" +#include "lldb/Interpreter/OptionValueEnumeration.h" +#include "lldb/Interpreter/OptionValueFileSpec.h" +#include "lldb/Interpreter/OptionValueFileSpecList.h" +#include "lldb/Interpreter/OptionValueFormat.h" +#include "lldb/Interpreter/OptionValuePathMappings.h" +#include "lldb/Interpreter/OptionValueProperties.h" +#include "lldb/Interpreter/OptionValueRegex.h" +#include "lldb/Interpreter/OptionValueSInt64.h" +#include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Interpreter/OptionValueUInt64.h" +#include "lldb/Interpreter/OptionValueUUID.h" + +#endif // liblldb_OptionValues_h_ diff --git a/include/lldb/Interpreter/Options.h b/include/lldb/Interpreter/Options.h new file mode 100644 index 0000000..ac4daa8 --- /dev/null +++ b/include/lldb/Interpreter/Options.h @@ -0,0 +1,487 @@ +//===-- Options.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_Options_h_ +#define liblldb_Options_h_ + +// C Includes +#include <getopt.h> + +// C++ Includes +#include <set> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/lldb-defines.h" +#include "lldb/Interpreter/Args.h" + +namespace lldb_private { + + static inline bool + isprint8 (int ch) + { + if (ch & 0xffffff00u) + return false; + return isprint(ch); + } + + +//---------------------------------------------------------------------- +/// @class Options Options.h "lldb/Interpreter/Options.h" +/// @brief A command line option parsing protocol class. +/// +/// Options is designed to be subclassed to contain all needed +/// options for a given command. The options can be parsed by calling: +/// \code +/// Error Args::ParseOptions (Options &); +/// \endcode +/// +/// The options are specified using the format defined for the libc +/// options parsing function getopt_long_only: +/// \code +/// #include <getopt.h> +/// int getopt_long_only(int argc, char * const *argv, const char *optstring, const struct option *longopts, int *longindex); +/// \endcode +/// +/// Example code: +/// \code +/// #include <getopt.h> +/// #include <string> +/// +/// class CommandOptions : public Options +/// { +/// public: +/// virtual struct option * +/// GetLongOptions() { +/// return g_options; +/// } +/// +/// virtual Error +/// SetOptionValue (uint32_t option_idx, int option_val, const char *option_arg) +/// { +/// Error error; +/// switch (option_val) +/// { +/// case 'g': debug = true; break; +/// case 'v': verbose = true; break; +/// case 'l': log_file = option_arg; break; +/// case 'f': log_flags = strtoull(option_arg, NULL, 0); break; +/// default: +/// error.SetErrorStringWithFormat("unrecognized short option %c", option_val); +/// break; +/// } +/// +/// return error; +/// } +/// +/// CommandOptions (CommandInterpreter &interpreter) : debug (true), verbose (false), log_file (), log_flags (0) +/// {} +/// +/// bool debug; +/// bool verbose; +/// std::string log_file; +/// uint32_t log_flags; +/// +/// static struct option g_options[]; +/// +/// }; +/// +/// struct option CommandOptions::g_options[] = +/// { +/// { "debug", no_argument, NULL, 'g' }, +/// { "log-file", required_argument, NULL, 'l' }, +/// { "log-flags", required_argument, NULL, 'f' }, +/// { "verbose", no_argument, NULL, 'v' }, +/// { NULL, 0, NULL, 0 } +/// }; +/// +/// int main (int argc, const char **argv, const char **envp) +/// { +/// CommandOptions options; +/// Args main_command; +/// main_command.SetArguments(argc, argv, false); +/// main_command.ParseOptions(options); +/// +/// if (options.verbose) +/// { +/// std::cout << "verbose is on" << std::endl; +/// } +/// } +/// \endcode +//---------------------------------------------------------------------- +class Options +{ +public: + + Options (CommandInterpreter &interpreter); + + virtual + ~Options (); + + void + BuildGetoptTable (); + + void + BuildValidOptionSets (); + + uint32_t + NumCommandOptions (); + + //------------------------------------------------------------------ + /// Get the option definitions to use when parsing Args options. + /// + /// @see Args::ParseOptions (Options&) + /// @see man getopt_long_only + //------------------------------------------------------------------ + struct option * + GetLongOptions (); + + // This gets passed the short option as an integer... + void + OptionSeen (int short_option); + + bool + VerifyOptions (CommandReturnObject &result); + + // Verify that the options given are in the options table and can + // be used together, but there may be some required options that are + // missing (used to verify options that get folded into command aliases). + + bool + VerifyPartialOptions (CommandReturnObject &result); + + void + OutputFormattedUsageText (Stream &strm, + const char *text, + uint32_t output_max_columns); + + void + GenerateOptionUsage (Stream &strm, + CommandObject *cmd); + + bool + SupportsLongOption (const char *long_option); + + // The following two pure virtual functions must be defined by every + // class that inherits from this class. + + virtual const OptionDefinition* + GetDefinitions () { return NULL; } + + // Call this prior to parsing any options. This call will call the + // subclass OptionParsingStarting() and will avoid the need for all + // OptionParsingStarting() function instances from having to call the + // Option::OptionParsingStarting() like they did before. This was error + // prone and subclasses shouldn't have to do it. + void + NotifyOptionParsingStarting (); + + Error + NotifyOptionParsingFinished (); + + //------------------------------------------------------------------ + /// Set the value of an option. + /// + /// @param[in] option_idx + /// The index into the "struct option" array that was returned + /// by Options::GetLongOptions(). + /// + /// @param[in] option_arg + /// The argument value for the option that the user entered, or + /// NULL if there is no argument for the current option. + /// + /// + /// @see Args::ParseOptions (Options&) + /// @see man getopt_long_only + //------------------------------------------------------------------ + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) = 0; + + //------------------------------------------------------------------ + /// Handles the generic bits of figuring out whether we are in an + /// option, and if so completing it. + /// + /// @param[in] input + /// The command line parsed into words + /// + /// @param[in] cursor_index + /// The index in \ainput of the word in which the cursor lies. + /// + /// @param[in] char_pos + /// The character position of the cursor in its argument word. + /// + /// @param[in] match_start_point + /// @param[in] match_return_elements + /// See CommandObject::HandleCompletions for a description of + /// how these work. + /// + /// @param[in] interpreter + /// The interpreter that's doing the completing. + /// + /// @param[out] word_complete + /// \btrue if this is a complete option value (a space will be + /// inserted after the completion.) \b false otherwise. + /// + /// @param[out] matches + /// The array of matches returned. + /// + /// FIXME: This is the wrong return value, since we also need to + /// make a distinction between total number of matches, and the + /// window the user wants returned. + /// + /// @return + /// \btrue if we were in an option, \bfalse otherwise. + //------------------------------------------------------------------ + bool + HandleOptionCompletion (Args &input, + OptionElementVector &option_map, + int cursor_index, + int char_pos, + int match_start_point, + int max_return_elements, + bool &word_complete, + lldb_private::StringList &matches); + + //------------------------------------------------------------------ + /// Handles the generic bits of figuring out whether we are in an + /// option, and if so completing it. + /// + /// @param[in] interpreter + /// The command interpreter doing the completion. + /// + /// @param[in] input + /// The command line parsed into words + /// + /// @param[in] cursor_index + /// The index in \ainput of the word in which the cursor lies. + /// + /// @param[in] char_pos + /// The character position of the cursor in its argument word. + /// + /// @param[in] opt_element_vector + /// The results of the options parse of \a input. + /// + /// @param[in] opt_element_index + /// The position in \a opt_element_vector of the word in \a + /// input containing the cursor. + /// + /// @param[in] match_start_point + /// @param[in] match_return_elements + /// See CommandObject::HandleCompletions for a description of + /// how these work. + /// + /// @param[out] word_complete + /// \btrue if this is a complete option value (a space will + /// be inserted after the completion.) \bfalse otherwise. + /// + /// @param[out] matches + /// The array of matches returned. + /// + /// FIXME: This is the wrong return value, since we also need to + /// make a distinction between total number of matches, and the + /// window the user wants returned. + /// + /// @return + /// \btrue if we were in an option, \bfalse otherwise. + //------------------------------------------------------------------ + virtual bool + HandleOptionArgumentCompletion (Args &input, + int cursor_index, + int char_pos, + OptionElementVector &opt_element_vector, + int opt_element_index, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + +protected: + // This is a set of options expressed as indexes into the options table for this Option. + typedef std::set<int> OptionSet; + typedef std::vector<OptionSet> OptionSetVector; + + CommandInterpreter &m_interpreter; + std::vector<struct option> m_getopt_table; + OptionSet m_seen_options; + OptionSetVector m_required_options; + OptionSetVector m_optional_options; + + OptionSetVector &GetRequiredOptions () + { + BuildValidOptionSets(); + return m_required_options; + } + + OptionSetVector &GetOptionalOptions () + { + BuildValidOptionSets(); + return m_optional_options; + } + + bool + IsASubset (const OptionSet& set_a, const OptionSet& set_b); + + size_t + OptionsSetDiff (const OptionSet &set_a, const OptionSet &set_b, OptionSet &diffs); + + void + OptionsSetUnion (const OptionSet &set_a, const OptionSet &set_b, OptionSet &union_set); + + // Subclasses must reset their option values prior to starting a new + // option parse. Each subclass must override this function and revert + // all option settings to default values. + virtual void + OptionParsingStarting () = 0; + + virtual Error + OptionParsingFinished () + { + // If subclasses need to know when the options are done being parsed + // they can implement this function to do extra checking + Error error; + return error; + } +}; + + class OptionGroup + { + public: + OptionGroup () + { + } + + virtual + ~OptionGroup () + { + } + + virtual uint32_t + GetNumDefinitions () = 0; + + virtual const OptionDefinition* + GetDefinitions () = 0; + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) = 0; + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter) = 0; + + virtual Error + OptionParsingFinished (CommandInterpreter &interpreter) + { + // If subclasses need to know when the options are done being parsed + // they can implement this function to do extra checking + Error error; + return error; + } + }; + + class OptionGroupOptions : public Options + { + public: + + OptionGroupOptions (CommandInterpreter &interpreter) : + Options (interpreter), + m_option_defs (), + m_option_infos (), + m_did_finalize (false) + { + } + + virtual + ~OptionGroupOptions () + { + } + + + //---------------------------------------------------------------------- + /// Append options from a OptionGroup class. + /// + /// Append all options from \a group using the exact same option groups + /// that each option is defined with. + /// + /// @param[in] group + /// A group of options to take option values from and copy their + /// definitions into this class. + //---------------------------------------------------------------------- + void + Append (OptionGroup* group); + + //---------------------------------------------------------------------- + /// Append options from a OptionGroup class. + /// + /// Append options from \a group that have a usage mask that has any bits + /// in "src_mask" set. After the option definition is copied into the + /// options definitions in this class, set the usage_mask to "dst_mask". + /// + /// @param[in] group + /// A group of options to take option values from and copy their + /// definitions into this class. + /// + /// @param[in] src_mask + /// When copying options from \a group, you might only want some of + /// the options to be appended to this group. This mask allows you + /// to control which options from \a group get added. It also allows + /// you to specify the same options from \a group multiple times + /// for different option sets. + /// + /// @param[in] dst_mask + /// Set the usage mask for any copied options to \a dst_mask after + /// copying the option definition. + //---------------------------------------------------------------------- + void + Append (OptionGroup* group, + uint32_t src_mask, + uint32_t dst_mask); + + void + Finalize (); + + virtual Error + SetOptionValue (uint32_t option_idx, + const char *option_arg); + + virtual void + OptionParsingStarting (); + + virtual Error + OptionParsingFinished (); + + const OptionDefinition* + GetDefinitions () + { + assert (m_did_finalize); + return &m_option_defs[0]; + } + struct OptionInfo + { + OptionInfo (OptionGroup* g, uint32_t i) : + option_group (g), + option_index (i) + { + } + OptionGroup* option_group; // The group that this option came from + uint32_t option_index; // The original option index from the OptionGroup + }; + typedef std::vector<OptionInfo> OptionInfos; + + std::vector<OptionDefinition> m_option_defs; + OptionInfos m_option_infos; + bool m_did_finalize; + }; + + +} // namespace lldb_private + +#endif // liblldb_Options_h_ diff --git a/include/lldb/Interpreter/Property.h b/include/lldb/Interpreter/Property.h new file mode 100644 index 0000000..b192758 --- /dev/null +++ b/include/lldb/Interpreter/Property.h @@ -0,0 +1,109 @@ +//===-- Property.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_Property_h_ +#define liblldb_Property_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-defines.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Flags.h" +#include "lldb/Interpreter/OptionValue.h" + +namespace lldb_private { + + // A structure that can be used to create a global table for all properties. + // Property class instances can be constructed using one of these. + struct PropertyDefinition + { + const char *name; + OptionValue::Type type; + bool global; + uintptr_t default_uint_value; + const char *default_cstr_value; + OptionEnumValueElement *enum_values; + const char *description; + }; + + class Property + { + public: + Property (const PropertyDefinition &definition); + + Property (const ConstString &name, + const ConstString &desc, + bool is_global, + const lldb::OptionValueSP &value_sp); + + const ConstString & + GetName() const + { + return m_name; + } + + const char * + GetDescription () const + { + return m_description.GetCString(); + } + + const lldb::OptionValueSP & + GetValue() const + { + return m_value_sp; + } + + void + SetOptionValue (const lldb::OptionValueSP &value_sp) + { + m_value_sp = value_sp; + } + + + bool + IsValid() const + { + return (bool)m_value_sp; + } + + bool + IsGlobal () const + { + return m_is_global; + } + + void + Dump (const ExecutionContext *exe_ctx, + Stream &strm, + uint32_t dump_mask) const; + + bool + DumpQualifiedName(Stream &strm) const; + + void + DumpDescription (CommandInterpreter &interpreter, + Stream &strm, + uint32_t output_width, + bool display_qualified_name) const; + + protected: + ConstString m_name; + ConstString m_description; + lldb::OptionValueSP m_value_sp; + bool m_is_global; + }; + +} // namespace lldb_private + +#endif // liblldb_Property_h_ diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h new file mode 100644 index 0000000..b2c9240 --- /dev/null +++ b/include/lldb/Interpreter/PythonDataObjects.h @@ -0,0 +1,233 @@ +//===-- PythonDataObjects.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_PythonDataObjects_h_ +#define liblldb_PythonDataObjects_h_ + +// C Includes +// C++ Includes + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-defines.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Flags.h" +#include "lldb/Interpreter/OptionValue.h" +#if defined (__APPLE__) +#include <Python/Python.h> +#else +#include <Python.h> +#endif + +namespace lldb_private { + + class PythonObject + { + public: + PythonObject () : + m_py_obj(NULL) + { + } + + PythonObject (PyObject* py_obj) : + m_py_obj(NULL) + { + Reset (py_obj); + } + + PythonObject (const PythonObject &rhs) : + m_py_obj(NULL) + { + Reset (rhs.m_py_obj); + } + + PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp); + + virtual + ~PythonObject () + { + Reset (NULL); + } + + const PythonObject & + operator = (const PythonObject &rhs) + { + if (this != &rhs) + Reset (rhs.m_py_obj); + return *this; + } + + bool + Reset (const PythonObject &object) + { + return Reset(object.GetPythonObject()); + } + + virtual bool + Reset (PyObject* py_obj = NULL) + { + if (py_obj != m_py_obj) + { + Py_XDECREF(m_py_obj); + m_py_obj = py_obj; + Py_XINCREF(m_py_obj); + } + return true; + } + + void + Dump () const + { + if (m_py_obj) + _PyObject_Dump (m_py_obj); + else + puts ("NULL"); + } + + void + Dump (Stream &strm) const; + + PyObject* + GetPythonObject () const + { + return m_py_obj; + } + + PythonString + Repr (); + + PythonString + Str (); + + operator bool () const + { + return m_py_obj != NULL; + } + + protected: + PyObject* m_py_obj; + }; + + class PythonString: public PythonObject + { + public: + + PythonString (); + PythonString (PyObject *o); + PythonString (const PythonObject &object); + PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp); + PythonString (const char* string); + virtual ~PythonString (); + + virtual bool + Reset (PyObject* py_obj = NULL); + + const char* + GetString() const; + + size_t + GetSize() const; + + void + SetString (const char* string); + }; + + class PythonInteger: public PythonObject + { + public: + + PythonInteger (); + PythonInteger (PyObject* py_obj); + PythonInteger (const PythonObject &object); + PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp); + PythonInteger (int64_t value); + virtual ~PythonInteger (); + + virtual bool + Reset (PyObject* py_obj = NULL); + + int64_t + GetInteger(); + + void + SetInteger (int64_t value); + }; + + class PythonList: public PythonObject + { + public: + + PythonList (); + PythonList (PyObject* py_obj); + PythonList (const PythonObject &object); + PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp); + PythonList (uint32_t count); + virtual ~PythonList (); + + virtual bool + Reset (PyObject* py_obj = NULL); + + uint32_t + GetSize(); + + PythonObject + GetItemAtIndex (uint32_t index); + + void + SetItemAtIndex (uint32_t index, const PythonObject &object); + + void + AppendItem (const PythonObject &object); + }; + + class PythonDictionary: public PythonObject + { + public: + + PythonDictionary (); + PythonDictionary (PyObject* object); + PythonDictionary (const PythonObject &object); + PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp); + virtual ~PythonDictionary (); + + virtual bool + Reset (PyObject* object = NULL); + + uint32_t GetSize(); + + PythonObject + GetItemForKey (const PythonString &key) const; + + const char * + GetItemForKeyAsString (const PythonString &key, const char *fail_value = NULL) const; + + int64_t + GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value = 0) const; + + PythonObject + GetItemForKey (const char *key) const; + + typedef bool (*DictionaryIteratorCallback)(PythonString* key, PythonDictionary* dict); + + PythonList + GetKeys () const; + + PythonString + GetKeyAtPosition (uint32_t pos) const; + + PythonObject + GetValueAtPosition (uint32_t pos) const; + + void + SetItemForKey (const PythonString &key, const PythonObject& value); + }; + +} // namespace lldb_private + +#endif // liblldb_PythonDataObjects_h_ diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h new file mode 100644 index 0000000..9a66c77 --- /dev/null +++ b/include/lldb/Interpreter/ScriptInterpreter.h @@ -0,0 +1,519 @@ +//===-- ScriptInterpreter.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_ScriptInterpreter_h_ +#define liblldb_ScriptInterpreter_h_ + +#include "lldb/lldb-private.h" + +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Error.h" + +#include "lldb/Utility/PseudoTerminal.h" + + +namespace lldb_private { + +class ScriptInterpreterObject +{ +public: + ScriptInterpreterObject() : + m_object(NULL) + {} + + ScriptInterpreterObject(void* obj) : + m_object(obj) + {} + + ScriptInterpreterObject(const ScriptInterpreterObject& rhs) + : m_object(rhs.m_object) + {} + + virtual void* + GetObject() + { + return m_object; + } + + operator bool () + { + return m_object != NULL; + } + + ScriptInterpreterObject& + operator = (const ScriptInterpreterObject& rhs) + { + if (this != &rhs) + m_object = rhs.m_object; + return *this; + } + + virtual + ~ScriptInterpreterObject() + {} + +protected: + void* m_object; +}; + +class ScriptInterpreterLocker +{ +public: + + ScriptInterpreterLocker () + { + } + + virtual ~ScriptInterpreterLocker () + { + } +private: + DISALLOW_COPY_AND_ASSIGN (ScriptInterpreterLocker); +}; + + +class ScriptInterpreter +{ +public: + + typedef void (*SWIGInitCallback) (void); + + typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& frame_sp, + const lldb::BreakpointLocationSP &bp_loc_sp); + + typedef bool (*SWIGWatchpointCallbackFunction) (const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& frame_sp, + const lldb::WatchpointSP &wp_sp); + + typedef bool (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name, + void *session_dictionary, + const lldb::ValueObjectSP& valobj_sp, + void** pyfunct_wrapper, + std::string& retval); + + typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp); + + typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP& process_sp); + + typedef uint32_t (*SWIGPythonCalculateNumChildren) (void *implementor); + typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); + typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); + typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data); + typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data); + typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data); + + + typedef bool (*SWIGPythonCallCommand) (const char *python_function_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger, + const char* args, + lldb_private::CommandReturnObject& cmd_retobj); + + typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger); + + typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name, + const char* session_dictionary_name, + lldb::ProcessSP& process, + std::string& output); + typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name, + const char* session_dictionary_name, + lldb::ThreadSP& thread, + std::string& output); + + typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name, + const char* session_dictionary_name, + lldb::TargetSP& target, + std::string& output); + + typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name, + const char* session_dictionary_name, + lldb::StackFrameSP& frame, + std::string& output); + + + + typedef enum + { + eScriptReturnTypeCharPtr, + eScriptReturnTypeBool, + eScriptReturnTypeShortInt, + eScriptReturnTypeShortIntUnsigned, + eScriptReturnTypeInt, + eScriptReturnTypeIntUnsigned, + eScriptReturnTypeLongInt, + eScriptReturnTypeLongIntUnsigned, + eScriptReturnTypeLongLong, + eScriptReturnTypeLongLongUnsigned, + eScriptReturnTypeFloat, + eScriptReturnTypeDouble, + eScriptReturnTypeChar, + eScriptReturnTypeCharStrOrNone + } ScriptReturnType; + + ScriptInterpreter (CommandInterpreter &interpreter, lldb::ScriptLanguage script_lang); + + virtual ~ScriptInterpreter (); + + struct ExecuteScriptOptions + { + public: + ExecuteScriptOptions () : + m_enable_io(true), + m_set_lldb_globals(true), + m_maskout_errors(true) + { + } + + bool + GetEnableIO () const + { + return m_enable_io; + } + + bool + GetSetLLDBGlobals () const + { + return m_set_lldb_globals; + } + + bool + GetMaskoutErrors () const + { + return m_maskout_errors; + } + + ExecuteScriptOptions& + SetEnableIO (bool enable) + { + m_enable_io = enable; + return *this; + } + + ExecuteScriptOptions& + SetSetLLDBGlobals (bool set) + { + m_set_lldb_globals = set; + return *this; + } + + ExecuteScriptOptions& + SetMaskoutErrors (bool maskout) + { + m_maskout_errors = maskout; + return *this; + } + + private: + bool m_enable_io; + bool m_set_lldb_globals; + bool m_maskout_errors; + }; + + virtual bool + ExecuteOneLine (const char *command, + CommandReturnObject *result, + const ExecuteScriptOptions &options = ExecuteScriptOptions()) = 0; + + virtual void + ExecuteInterpreterLoop () = 0; + + virtual bool + ExecuteOneLineWithReturn (const char *in_string, + ScriptReturnType return_type, + void *ret_value, + const ExecuteScriptOptions &options = ExecuteScriptOptions()) + { + return true; + } + + virtual bool + ExecuteMultipleLines (const char *in_string, + const ExecuteScriptOptions &options = ExecuteScriptOptions()) + { + return true; + } + + virtual bool + ExportFunctionDefinitionToInterpreter (StringList &function_def) + { + return false; + } + + virtual bool + GenerateBreakpointCommandCallbackData (StringList &input, std::string& output) + { + return false; + } + + virtual bool + GenerateWatchpointCommandCallbackData (StringList &input, std::string& output) + { + return false; + } + + virtual bool + GenerateTypeScriptFunction (const char* oneliner, std::string& output, void* name_token = NULL) + { + return false; + } + + virtual bool + GenerateTypeScriptFunction (StringList &input, std::string& output, void* name_token = NULL) + { + return false; + } + + virtual bool + GenerateScriptAliasFunction (StringList &input, std::string& output) + { + return false; + } + + virtual bool + GenerateTypeSynthClass (StringList &input, std::string& output, void* name_token = NULL) + { + return false; + } + + virtual bool + GenerateTypeSynthClass (const char* oneliner, std::string& output, void* name_token = NULL) + { + return false; + } + + virtual lldb::ScriptInterpreterObjectSP + CreateSyntheticScriptedProvider (const char *class_name, + lldb::ValueObjectSP valobj) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_CreatePluginObject (const char *class_name, + lldb::ProcessSP process_sp) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t thread_id) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t tid, + lldb::addr_t context) + { + return lldb::ScriptInterpreterObjectSP(); + } + + virtual bool + GenerateFunction(const char *signature, const StringList &input) + { + return false; + } + + virtual void + CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, + CommandReturnObject &result); + + virtual void + CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, + CommandReturnObject &result); + + /// Set a one-liner as the callback for the breakpoint. + virtual void + SetBreakpointCommandCallback (BreakpointOptions *bp_options, + const char *oneliner) + { + return; + } + + /// Set a one-liner as the callback for the watchpoint. + virtual void + SetWatchpointCommandCallback (WatchpointOptions *wp_options, + const char *oneliner) + { + return; + } + + virtual bool + GetScriptedSummary (const char *function_name, + lldb::ValueObjectSP valobj, + lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, + std::string& retval) + { + return false; + } + + virtual size_t + CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor) + { + return 0; + } + + virtual lldb::ValueObjectSP + GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor, uint32_t idx) + { + return lldb::ValueObjectSP(); + } + + virtual int + GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor, const char* child_name) + { + return UINT32_MAX; + } + + virtual bool + UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) + { + return false; + } + + virtual bool + MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor) + { + return true; + } + + virtual bool + RunScriptBasedCommand (const char* impl_function, + const char* args, + ScriptedCommandSynchronicity synchronicity, + lldb_private::CommandReturnObject& cmd_retobj, + Error& error) + { + return false; + } + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + Process* process, + std::string& output, + Error& error) + { + error.SetErrorString("unimplemented"); + return false; + } + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + Thread* thread, + std::string& output, + Error& error) + { + error.SetErrorString("unimplemented"); + return false; + } + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + Target* target, + std::string& output, + Error& error) + { + error.SetErrorString("unimplemented"); + return false; + } + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + StackFrame* frame, + std::string& output, + Error& error) + { + error.SetErrorString("unimplemented"); + return false; + } + + virtual bool + GetDocumentationForItem (const char* item, std::string& dest) + { + dest.clear(); + return false; + } + + virtual bool + CheckObjectExists (const char* name) + { + return false; + } + + virtual bool + LoadScriptingModule (const char* filename, + bool can_reload, + bool init_session, + lldb_private::Error& error) + { + error.SetErrorString("loading unimplemented"); + return false; + } + + virtual lldb::ScriptInterpreterObjectSP + MakeScriptObject (void* object) + { + return lldb::ScriptInterpreterObjectSP(new ScriptInterpreterObject(object)); + } + + virtual std::unique_ptr<ScriptInterpreterLocker> + AcquireInterpreterLock (); + + const char * + GetScriptInterpreterPtyName (); + + int + GetMasterFileDescriptor (); + + CommandInterpreter & + GetCommandInterpreter (); + + static std::string + LanguageToString (lldb::ScriptLanguage language); + + static void + InitializeInterpreter (SWIGInitCallback python_swig_init_callback); + + static void + TerminateInterpreter (); + + virtual void + ResetOutputFileHandle (FILE *new_fh) { } //By default, do nothing. + +protected: + CommandInterpreter &m_interpreter; + lldb::ScriptLanguage m_script_lang; +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_ScriptInterpreter_h_ diff --git a/include/lldb/Interpreter/ScriptInterpreterNone.h b/include/lldb/Interpreter/ScriptInterpreterNone.h new file mode 100644 index 0000000..6c82b60 --- /dev/null +++ b/include/lldb/Interpreter/ScriptInterpreterNone.h @@ -0,0 +1,35 @@ +//===-- ScriptInterpreterNone.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_ScriptInterpreterNone_h_ +#define liblldb_ScriptInterpreterNone_h_ + +#include "lldb/Interpreter/ScriptInterpreter.h" + +namespace lldb_private { + +class ScriptInterpreterNone : public ScriptInterpreter +{ +public: + + ScriptInterpreterNone (CommandInterpreter &interpreter); + + ~ScriptInterpreterNone (); + + bool + ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options = ExecuteScriptOptions()); + + void + ExecuteInterpreterLoop (); + +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_ScriptInterpreterNone_h_ diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h new file mode 100644 index 0000000..2616f57 --- /dev/null +++ b/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -0,0 +1,407 @@ +//===-- ScriptInterpreterPython.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_ScriptInterpreterPython_h_ +#define liblldb_ScriptInterpreterPython_h_ + +#ifdef LLDB_DISABLE_PYTHON + +// Python is disabled in this build + +#else + +#if defined (__APPLE__) +#include <Python/Python.h> +#else +#include <Python.h> +#endif + +#include "lldb/lldb-private.h" +#include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/Core/InputReader.h" +#include "lldb/Host/Terminal.h" + +namespace lldb_private { + +class ScriptInterpreterPython : public ScriptInterpreter +{ +public: + + ScriptInterpreterPython (CommandInterpreter &interpreter); + + ~ScriptInterpreterPython (); + + bool + ExecuteOneLine (const char *command, + CommandReturnObject *result, + const ExecuteScriptOptions &options = ExecuteScriptOptions()); + + void + ExecuteInterpreterLoop (); + + bool + ExecuteOneLineWithReturn (const char *in_string, + ScriptInterpreter::ScriptReturnType return_type, + void *ret_value, + const ExecuteScriptOptions &options = ExecuteScriptOptions()); + + bool + ExecuteMultipleLines (const char *in_string, + const ExecuteScriptOptions &options = ExecuteScriptOptions()); + + bool + ExportFunctionDefinitionToInterpreter (StringList &function_def); + + bool + GenerateTypeScriptFunction (StringList &input, std::string& output, void* name_token = NULL); + + bool + GenerateTypeSynthClass (StringList &input, std::string& output, void* name_token = NULL); + + bool + GenerateTypeSynthClass (const char* oneliner, std::string& output, void* name_token = NULL); + + // use this if the function code is just a one-liner script + bool + GenerateTypeScriptFunction (const char* oneliner, std::string& output, void* name_token = NULL); + + virtual bool + GenerateScriptAliasFunction (StringList &input, std::string& output); + + lldb::ScriptInterpreterObjectSP + CreateSyntheticScriptedProvider (const char *class_name, + lldb::ValueObjectSP valobj); + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_CreatePluginObject (const char *class_name, + lldb::ProcessSP process_sp); + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp); + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp); + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t thread_id); + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t tid, + lldb::addr_t context); + + virtual size_t + CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor); + + virtual lldb::ValueObjectSP + GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor, uint32_t idx); + + virtual int + GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor, const char* child_name); + + virtual bool + UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor); + + virtual bool + MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor); + + virtual bool + RunScriptBasedCommand(const char* impl_function, + const char* args, + ScriptedCommandSynchronicity synchronicity, + lldb_private::CommandReturnObject& cmd_retobj, + Error& error); + + bool + GenerateFunction(const char *signature, const StringList &input); + + bool + GenerateBreakpointCommandCallbackData (StringList &input, std::string& output); + + bool + GenerateWatchpointCommandCallbackData (StringList &input, std::string& output); + + static size_t + GenerateBreakpointOptionsCommandCallback (void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + static size_t + GenerateWatchpointOptionsCommandCallback (void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + static bool + BreakpointCallbackFunction (void *baton, + StoppointCallbackContext *context, + lldb::user_id_t break_id, + lldb::user_id_t break_loc_id); + + static bool + WatchpointCallbackFunction (void *baton, + StoppointCallbackContext *context, + lldb::user_id_t watch_id); + + virtual bool + GetScriptedSummary (const char *function_name, + lldb::ValueObjectSP valobj, + lldb::ScriptInterpreterObjectSP& callee_wrapper_sp, + std::string& retval); + + virtual bool + GetDocumentationForItem (const char* item, std::string& dest); + + virtual bool + CheckObjectExists (const char* name) + { + if (!name || !name[0]) + return false; + std::string temp; + return GetDocumentationForItem (name,temp); + } + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + Process* process, + std::string& output, + Error& error); + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + Thread* thread, + std::string& output, + Error& error); + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + Target* target, + std::string& output, + Error& error); + + virtual bool + RunScriptFormatKeyword (const char* impl_function, + StackFrame* frame, + std::string& output, + Error& error); + + virtual bool + LoadScriptingModule (const char* filename, + bool can_reload, + bool init_session, + lldb_private::Error& error); + + virtual lldb::ScriptInterpreterObjectSP + MakeScriptObject (void* object); + + virtual std::unique_ptr<ScriptInterpreterLocker> + AcquireInterpreterLock (); + + void + CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options, + CommandReturnObject &result); + + void + CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options, + CommandReturnObject &result); + + /// Set a Python one-liner as the callback for the breakpoint. + void + SetBreakpointCommandCallback (BreakpointOptions *bp_options, + const char *oneliner); + + /// Set a one-liner as the callback for the watchpoint. + void + SetWatchpointCommandCallback (WatchpointOptions *wp_options, + const char *oneliner); + + StringList + ReadCommandInputFromUser (FILE *in_file); + + virtual void + ResetOutputFileHandle (FILE *new_fh); + + static lldb::thread_result_t + RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton); + + static void + InitializePrivate (); + + static void + InitializeInterpreter (SWIGInitCallback python_swig_init_callback); + +protected: + + bool + EnterSession (bool init_lldb_globals); + + void + LeaveSession (); + + void + SaveTerminalState (int fd); + + void + RestoreTerminalState (); + +private: + + class SynchronicityHandler + { + private: + lldb::DebuggerSP m_debugger_sp; + ScriptedCommandSynchronicity m_synch_wanted; + bool m_old_asynch; + public: + SynchronicityHandler(lldb::DebuggerSP, + ScriptedCommandSynchronicity); + ~SynchronicityHandler(); + }; + + class ScriptInterpreterPythonObject : public ScriptInterpreterObject + { + public: + ScriptInterpreterPythonObject() : + ScriptInterpreterObject() + {} + + ScriptInterpreterPythonObject(void* obj) : + ScriptInterpreterObject(obj) + { + Py_XINCREF(m_object); + } + + operator bool () + { + return m_object && m_object != Py_None; + } + + + virtual + ~ScriptInterpreterPythonObject() + { + Py_XDECREF(m_object); + m_object = NULL; + } + private: + DISALLOW_COPY_AND_ASSIGN (ScriptInterpreterPythonObject); + }; + + class Locker : public ScriptInterpreterLocker + { + public: + + enum OnEntry + { + AcquireLock = 0x0001, + InitSession = 0x0002, + InitGlobals = 0x0004 + }; + + enum OnLeave + { + FreeLock = 0x0001, + FreeAcquiredLock = 0x0002, // do not free the lock if we already held it when calling constructor + TearDownSession = 0x0004 + }; + + Locker (ScriptInterpreterPython *py_interpreter = NULL, + uint16_t on_entry = AcquireLock | InitSession, + uint16_t on_leave = FreeLock | TearDownSession, + FILE* wait_msg_handle = NULL); + + ~Locker (); + + private: + + bool + DoAcquireLock (); + + bool + DoInitSession (bool init_lldb_globals); + + bool + DoFreeLock (); + + bool + DoTearDownSession (); + + static void + ReleasePythonLock (); + + bool m_teardown_session; + ScriptInterpreterPython *m_python_interpreter; + FILE* m_tmp_fh; + PyGILState_STATE m_GILState; + }; + + class PythonInputReaderManager + { + public: + PythonInputReaderManager (ScriptInterpreterPython *interpreter); + + operator bool() + { + return m_error; + } + + ~PythonInputReaderManager(); + + private: + + static size_t + InputReaderCallback (void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + static lldb::thread_result_t + RunPythonInputReader (lldb::thread_arg_t baton); + + ScriptInterpreterPython *m_interpreter; + lldb::DebuggerSP m_debugger_sp; + lldb::InputReaderSP m_reader_sp; + bool m_error; + }; + + static size_t + InputReaderCallback (void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + + lldb_utility::PseudoTerminal m_embedded_thread_pty; + lldb_utility::PseudoTerminal m_embedded_python_pty; + lldb::InputReaderSP m_embedded_thread_input_reader_sp; + lldb::InputReaderSP m_embedded_python_input_reader_sp; + FILE *m_dbg_stdout; + PyObject *m_new_sysout; + PyObject *m_old_sysout; + PyObject *m_old_syserr; + PyObject *m_run_one_line; + std::string m_dictionary_name; + TerminalState m_terminal_state; + bool m_session_is_active; + bool m_pty_slave_is_open; + bool m_valid_session; + PyThreadState *m_command_thread_state; +}; +} // namespace lldb_private + +#endif // #ifdef LLDB_DISABLE_PYTHON + +#endif // #ifndef liblldb_ScriptInterpreterPython_h_ diff --git a/include/lldb/Symbol/Block.h b/include/lldb/Symbol/Block.h new file mode 100644 index 0000000..a2d703b --- /dev/null +++ b/include/lldb/Symbol/Block.h @@ -0,0 +1,496 @@ +//===-- Block.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_Block_h_ +#define liblldb_Block_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/LineEntry.h" +#include "lldb/Symbol/SymbolContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Block Block.h "lldb/Symbol/Block.h" +/// @brief A class that describes a single lexical block. +/// +/// A Function object owns a BlockList object which owns one or more +/// Block objects. The BlockList object contains a section offset +/// address range, and Block objects contain one or more ranges +/// which are offsets into that range. Blocks are can have discontiguous +/// ranges within the BlockList adress range, and each block can +/// contain child blocks each with their own sets of ranges. +/// +/// Each block has a variable list that represents local, argument, and +/// static variables that are scoped to the block. +/// +/// Inlined functions are representated by attaching a +/// InlineFunctionInfo shared pointer object to a block. Inlined +/// functions are represented as named blocks. +//---------------------------------------------------------------------- +class Block : + public UserID, + public SymbolContextScope +{ +public: + typedef RangeArray<uint32_t, uint32_t, 1> RangeList; + typedef RangeList::Entry Range; + + //------------------------------------------------------------------ + /// Construct with a User ID \a uid, \a depth. + /// + /// Initialize this block with the specified UID \a uid. The + /// \a depth in the \a block_list is used to represent the parent, + /// sibling, and child block information and also allows for partial + /// parsing at the block level. + /// + /// @param[in] uid + /// The UID for a given block. This value is given by the + /// SymbolFile plug-in and can be any value that helps the + /// SymbolFile plug-in to match this block back to the debug + /// information data that it parses for further or more in + /// depth parsing. Common values would be the index into a + /// table, or an offset into the debug information. + /// + /// @param[in] depth + /// The integer depth of this block in the block list hierarchy. + /// + /// @param[in] block_list + /// The block list that this object belongs to. + /// + /// @see BlockList + //------------------------------------------------------------------ + Block (lldb::user_id_t uid); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + virtual ~Block (); + + //------------------------------------------------------------------ + /// Add a child to this object. + /// + /// @param[in] child_block_sp + /// A shared pointer to a child block that will get added to + /// this block. + //------------------------------------------------------------------ + void + AddChild (const lldb::BlockSP &child_block_sp); + + //------------------------------------------------------------------ + /// Add a new offset range to this block. + /// + /// @param[in] start_offset + /// An offset into this Function's address range that + /// describes the start address of a range for this block. + /// + /// @param[in] end_offset + /// An offset into this Function's address range that + /// describes the end address of a range for this block. + //------------------------------------------------------------------ + void + AddRange (const Range& range); + + void + FinalizeRanges (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext(SymbolContext* sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual CompileUnit * + CalculateSymbolContextCompileUnit (); + + virtual Function * + CalculateSymbolContextFunction (); + + virtual Block * + CalculateSymbolContextBlock (); + + //------------------------------------------------------------------ + /// Check if an offset is in one of the block offset ranges. + /// + /// @param[in] range_offset + /// An offset into the Function's address range. + /// + /// @return + /// Returns \b true if \a range_offset falls in one of this + /// block's ranges, \b false otherwise. + //------------------------------------------------------------------ + bool + Contains (lldb::addr_t range_offset) const; + + //------------------------------------------------------------------ + /// Check if a offset range is in one of the block offset ranges. + /// + /// @param[in] range + /// An offset range into the Function's address range. + /// + /// @return + /// Returns \b true if \a range falls in one of this + /// block's ranges, \b false otherwise. + //------------------------------------------------------------------ + bool + Contains (const Range& range) const; + + //------------------------------------------------------------------ + /// Check if this object contains "block" as a child block at any + /// depth. + /// + /// @param[in] block + /// A potential child block. + /// + /// @return + /// Returns \b true if \a block is a child of this block, \b + /// false otherwise. + //------------------------------------------------------------------ + bool + Contains (const Block *block) const; + + //------------------------------------------------------------------ + /// Dump the block contents. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] base_addr + /// The resolved start address of the Function's address + /// range. This should be resolved as the file or load address + /// prior to passing the value into this function for dumping. + /// + /// @param[in] depth + /// Limit the number of levels deep that this function should + /// print as this block can contain child blocks. Specify + /// INT_MAX to dump all child blocks. + /// + /// @param[in] show_context + /// If \b true, variables will dump their context information. + //------------------------------------------------------------------ + void + Dump (Stream *s, lldb::addr_t base_addr, int32_t depth, bool show_context) const; + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext(Stream *s); + + void + DumpAddressRanges (Stream *s, + lldb::addr_t base_addr); + + void + GetDescription (Stream *s, + Function *function, + lldb::DescriptionLevel level, + Target *target) const; + + //------------------------------------------------------------------ + /// Get the parent block. + /// + /// @return + /// The parent block pointer, or NULL if this block has no + /// parent. + //------------------------------------------------------------------ + Block * + GetParent () const; + + + //------------------------------------------------------------------ + /// Get the inlined block that contains this block. + /// + /// @return + /// If this block contains inlined function info, it will return + /// this block, else parent blocks will be searched to see if + /// any contain this block. NULL will be returned if this block + /// nor any parent blocks are inlined function blocks. + //------------------------------------------------------------------ + Block * + GetContainingInlinedBlock (); + + //------------------------------------------------------------------ + /// Get the inlined parent block for this block. + /// + /// @return + /// The parent block pointer, or NULL if this block has no + /// parent. + //------------------------------------------------------------------ + Block * + GetInlinedParent (); + + //------------------------------------------------------------------ + /// Get the sibling block for this block. + /// + /// @return + /// The sibling block pointer, or NULL if this block has no + /// sibling. + //------------------------------------------------------------------ + Block * + GetSibling () const; + + //------------------------------------------------------------------ + /// Get the first child block. + /// + /// @return + /// The first child block pointer, or NULL if this block has no + /// children. + //------------------------------------------------------------------ + Block * + GetFirstChild () const + { + if (m_children.empty()) + return NULL; + return m_children.front().get(); + } + + //------------------------------------------------------------------ + /// Get the variable list for this block only. + /// + /// @param[in] can_create + /// If \b true, the variables can be parsed if they already + /// haven't been, else the current state of the block will be + /// returned. + /// + /// @return + /// A variable list shared pointer that contains all variables + /// for this block. + //------------------------------------------------------------------ + lldb::VariableListSP + GetBlockVariableList (bool can_create); + + + //------------------------------------------------------------------ + /// Get the variable list for this block and optionally all child + /// blocks if \a get_child_variables is \b true. + /// + /// @param[in] get_child_variables + /// If \b true, all variables from all child blocks will be + /// added to the variable list. + /// + /// @param[in] can_create + /// If \b true, the variables can be parsed if they already + /// haven't been, else the current state of the block will be + /// returned. Passing \b true for this parameter can be used + /// to see the current state of what has been parsed up to this + /// point. + /// + /// @param[in] add_inline_child_block_variables + /// If this is \b false, no child variables of child blocks + /// that are inlined functions will be gotten. If \b true then + /// all child variables will be added regardless of whether they + /// come from inlined functions or not. + /// + /// @return + /// A variable list shared pointer that contains all variables + /// for this block. + //------------------------------------------------------------------ + uint32_t + AppendBlockVariables (bool can_create, + bool get_child_block_variables, + bool stop_if_child_block_is_inlined_function, + VariableList *variable_list); + + //------------------------------------------------------------------ + /// Appends the variables from this block, and optionally from all + /// parent blocks, to \a variable_list. + /// + /// @param[in] can_create + /// If \b true, the variables can be parsed if they already + /// haven't been, else the current state of the block will be + /// returned. Passing \b true for this parameter can be used + /// to see the current state of what has been parsed up to this + /// point. + /// + /// @param[in] get_parent_variables + /// If \b true, all variables from all parent blocks will be + /// added to the variable list. + /// + /// @param[in] stop_if_block_is_inlined_function + /// If \b true, all variables from all parent blocks will be + /// added to the variable list until there are no parent blocks + /// or the parent block has inlined function info. + /// + /// @param[in/out] variable_list + /// All variables in this block, and optionally all parent + /// blocks will be added to this list. + /// + /// @return + /// The number of variable that were appended to \a + /// variable_list. + //------------------------------------------------------------------ + uint32_t + AppendVariables (bool can_create, + bool get_parent_variables, + bool stop_if_block_is_inlined_function, + VariableList *variable_list); + + //------------------------------------------------------------------ + /// Get const accessor for any inlined function information. + /// + /// @return + /// A comst pointer to any inlined function information, or NULL + /// if this is a regular block. + //------------------------------------------------------------------ + const InlineFunctionInfo* + GetInlinedFunctionInfo () const + { + return m_inlineInfoSP.get(); + } + + clang::DeclContext * + GetClangDeclContext(); + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// Returns the cost of this object plus any owned objects from the + /// ranges, variables, and inline function information. + /// + /// @return + /// The number of bytes that this object occupies in memory. + //------------------------------------------------------------------ + size_t + MemorySize() const; + + //------------------------------------------------------------------ + /// Set accessor for any inlined function information. + /// + /// @param[in] name + /// The method name for the inlined function. This value should + /// not be NULL. + /// + /// @param[in] mangled + /// The mangled method name for the inlined function. This can + /// be NULL if there is no mangled name for an inlined function + /// or if the name is the same as \a name. + /// + /// @param[in] decl_ptr + /// A optional pointer to declaration information for the + /// inlined function information. This value can be NULL to + /// indicate that no declaration information is available. + /// + /// @param[in] call_decl_ptr + /// Optional calling location declaration information that + /// describes from where this inlined function was called. + //------------------------------------------------------------------ + void + SetInlinedFunctionInfo (const char *name, + const char *mangled, + const Declaration *decl_ptr, + const Declaration *call_decl_ptr); + + + void + SetParentScope (SymbolContextScope *parent_scope) + { + m_parent_scope = parent_scope; + } + + //------------------------------------------------------------------ + /// Set accessor for the variable list. + /// + /// Called by the SymbolFile plug-ins after they have parsed the + /// variable lists and are ready to hand ownership of the list over + /// to this object. + /// + /// @param[in] variable_list_sp + /// A shared pointer to a VariableList. + //------------------------------------------------------------------ + void + SetVariableList (lldb::VariableListSP& variable_list_sp) + { + m_variable_list_sp = variable_list_sp; + } + + + + bool + BlockInfoHasBeenParsed() const + { + return m_parsed_block_info; + } + + void + SetBlockInfoHasBeenParsed (bool b, bool set_children); + + Block * + FindBlockByID (lldb::user_id_t block_id); + + size_t + GetNumRanges () const + { + return m_ranges.GetSize(); + } + + bool + GetRangeContainingOffset (const lldb::addr_t offset, Range &range); + + bool + GetRangeContainingAddress (const Address& addr, AddressRange &range); + + bool + GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range); + + uint32_t + GetRangeIndexContainingAddress (const Address& addr); + + //------------------------------------------------------------------ + // Since blocks might have multiple discontiguous addresss ranges, + // we need to be able to get at any of the address ranges in a block. + //------------------------------------------------------------------ + bool + GetRangeAtIndex (uint32_t range_idx, + AddressRange &range); + + bool + GetStartAddress (Address &addr); + + void + SetDidParseVariables (bool b, bool set_children); + +protected: + typedef std::vector<lldb::BlockSP> collection; + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + SymbolContextScope *m_parent_scope; + collection m_children; + RangeList m_ranges; + lldb::InlineFunctionInfoSP m_inlineInfoSP; ///< Inlined function information. + lldb::VariableListSP m_variable_list_sp; ///< The variable list for all local, static and paramter variables scoped to this block. + bool m_parsed_block_info:1, ///< Set to true if this block and it's children have all been parsed + m_parsed_block_variables:1, + m_parsed_child_blocks:1; + + // A parent of child blocks can be asked to find a sibling block given + // one of its child blocks + Block * + GetSiblingForChild (const Block *child_block) const; + +private: + DISALLOW_COPY_AND_ASSIGN (Block); +}; + + +} // namespace lldb_private + +#endif // liblldb_Block_h_ diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h new file mode 100644 index 0000000..75fc07b --- /dev/null +++ b/include/lldb/Symbol/ClangASTContext.h @@ -0,0 +1,441 @@ +//===-- ClangASTContext.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_ClangASTContext_h_ +#define liblldb_ClangASTContext_h_ + +// C Includes +#include <stdint.h> + +// C++ Includes +#include <string> +#include <vector> + +// Other libraries and framework includes +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/TemplateBase.h" + + +// Project includes +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/ClangASTType.h" + +namespace lldb_private { + +class Declaration; + +class ClangASTContext +{ +public: + typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); + typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ClangASTContext (const char *triple = NULL); + + ~ClangASTContext(); + + clang::ASTContext * + getASTContext(); + + clang::Builtin::Context * + getBuiltinContext(); + + clang::IdentifierTable * + getIdentifierTable(); + + clang::LangOptions * + getLanguageOptions(); + + clang::SelectorTable * + getSelectorTable(); + + clang::FileManager * + getFileManager(); + + clang::SourceManager * + getSourceManager(); + + clang::DiagnosticsEngine * + getDiagnosticsEngine(); + + clang::DiagnosticConsumer * + getDiagnosticConsumer(); + + clang::TargetOptions * + getTargetOptions(); + + clang::TargetInfo * + getTargetInfo(); + + void + Clear(); + + const char * + GetTargetTriple (); + + void + SetTargetTriple (const char *target_triple); + + void + SetArchitecture (const ArchSpec &arch); + + bool + HasExternalSource (); + + void + SetExternalSource (llvm::OwningPtr<clang::ExternalASTSource> &ast_source_ap); + + void + RemoveExternalSource (); + + bool + GetCompleteDecl (clang::Decl *decl) + { + return ClangASTContext::GetCompleteDecl(getASTContext(), decl); + } + + static bool + GetCompleteDecl (clang::ASTContext *ast, + clang::Decl *decl); + + void SetMetadataAsUserID (const void *object, + lldb::user_id_t user_id); + + void SetMetadata (const void *object, + ClangASTMetadata &meta_data) + { + SetMetadata(getASTContext(), object, meta_data); + } + + static void + SetMetadata (clang::ASTContext *ast, + const void *object, + ClangASTMetadata &meta_data); + + ClangASTMetadata * + GetMetadata (const void *object) + { + return GetMetadata(getASTContext(), object); + } + + static ClangASTMetadata * + GetMetadata (clang::ASTContext *ast, + const void *object); + + //------------------------------------------------------------------ + // Basic Types + //------------------------------------------------------------------ + ClangASTType + GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding, + uint32_t bit_size); + + static ClangASTType + GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast, + lldb::Encoding encoding, + uint32_t bit_size); + + ClangASTType + GetBasicType (lldb::BasicType type); + + static ClangASTType + GetBasicType (clang::ASTContext *ast, lldb::BasicType type); + + static ClangASTType + GetBasicType (clang::ASTContext *ast, const ConstString &name); + + static lldb::BasicType + GetBasicTypeEnumeration (const ConstString &name); + + ClangASTType + GetBuiltinTypeForDWARFEncodingAndBitSize ( + const char *type_name, + uint32_t dw_ate, + uint32_t bit_size); + + ClangASTType + GetCStringType(bool is_const); + + static ClangASTType + GetUnknownAnyType(clang::ASTContext *ast); + + ClangASTType + GetUnknownAnyType() + { + return ClangASTContext::GetUnknownAnyType(getASTContext()); + } + + uint32_t + GetPointerByteSize (); + + static clang::DeclContext * + GetTranslationUnitDecl (clang::ASTContext *ast); + + clang::DeclContext * + GetTranslationUnitDecl () + { + return GetTranslationUnitDecl (getASTContext()); + } + + static bool + GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx, + lldb::LanguageType &language, + bool &is_instance_method, + ConstString &language_object_name); + + static ClangASTType + CopyType(clang::ASTContext *dest_context, + ClangASTType source_type); + + static clang::Decl * + CopyDecl (clang::ASTContext *dest_context, + clang::ASTContext *source_context, + clang::Decl *source_decl); + + static bool + AreTypesSame(ClangASTType type1, + ClangASTType type2, + bool ignore_qualifiers = false); + + ClangASTType + GetTypeForDecl (clang::TagDecl *decl); + + ClangASTType + GetTypeForDecl (clang::ObjCInterfaceDecl *objc_decl); + + //------------------------------------------------------------------ + // Structure, Unions, Classes + //------------------------------------------------------------------ + + static clang::AccessSpecifier + ConvertAccessTypeToAccessSpecifier (lldb::AccessType access); + + static clang::AccessSpecifier + UnifyAccessSpecifiers (clang::AccessSpecifier lhs, clang::AccessSpecifier rhs); + + static uint32_t + GetNumBaseClasses (const clang::CXXRecordDecl *cxx_record_decl, + bool omit_empty_base_classes); + + static uint32_t + GetIndexForRecordBase (const clang::RecordDecl *record_decl, + const clang::CXXBaseSpecifier *base_spec, + bool omit_empty_base_classes); + + ClangASTType + CreateRecordType (clang::DeclContext *decl_ctx, + lldb::AccessType access_type, + const char *name, + int kind, + lldb::LanguageType language, + ClangASTMetadata *metadata = NULL); + + class TemplateParameterInfos + { + public: + bool + IsValid() const + { + if (args.empty()) + return false; + return args.size() == names.size(); + } + + size_t + GetSize () const + { + if (IsValid()) + return args.size(); + return 0; + } + + llvm::SmallVector<const char *, 8> names; + llvm::SmallVector<clang::TemplateArgument, 8> args; + }; + + clang::FunctionTemplateDecl * + CreateFunctionTemplateDecl (clang::DeclContext *decl_ctx, + clang::FunctionDecl *func_decl, + const char *name, + const TemplateParameterInfos &infos); + + void + CreateFunctionTemplateSpecializationInfo (clang::FunctionDecl *func_decl, + clang::FunctionTemplateDecl *Template, + const TemplateParameterInfos &infos); + + clang::ClassTemplateDecl * + CreateClassTemplateDecl (clang::DeclContext *decl_ctx, + lldb::AccessType access_type, + const char *class_name, + int kind, + const TemplateParameterInfos &infos); + + clang::ClassTemplateSpecializationDecl * + CreateClassTemplateSpecializationDecl (clang::DeclContext *decl_ctx, + clang::ClassTemplateDecl *class_template_decl, + int kind, + const TemplateParameterInfos &infos); + + ClangASTType + CreateClassTemplateSpecializationType (clang::ClassTemplateSpecializationDecl *class_template_specialization_decl); + + static clang::DeclContext * + GetAsDeclContext (clang::CXXMethodDecl *cxx_method_decl); + + static clang::DeclContext * + GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl); + + + static bool + CheckOverloadedOperatorKindParameterCount (uint32_t op_kind, + uint32_t num_params); + + bool + FieldIsBitfield (clang::FieldDecl* field, + uint32_t& bitfield_bit_size); + + static bool + FieldIsBitfield (clang::ASTContext *ast, + clang::FieldDecl* field, + uint32_t& bitfield_bit_size); + + static bool + RecordHasFields (const clang::RecordDecl *record_decl); + + + ClangASTType + CreateObjCClass (const char *name, + clang::DeclContext *decl_ctx, + bool isForwardDecl, + bool isInternal, + ClangASTMetadata *metadata = NULL); + + // Returns a mask containing bits from the ClangASTContext::eTypeXXX enumerations + + + //------------------------------------------------------------------ + // Namespace Declarations + //------------------------------------------------------------------ + + clang::NamespaceDecl * + GetUniqueNamespaceDeclaration (const char *name, + clang::DeclContext *decl_ctx); + + //------------------------------------------------------------------ + // Function Types + //------------------------------------------------------------------ + + clang::FunctionDecl * + CreateFunctionDeclaration (clang::DeclContext *decl_ctx, + const char *name, + const ClangASTType &function_Type, + int storage, + bool is_inline); + + static ClangASTType + CreateFunctionType (clang::ASTContext *ast, + const ClangASTType &result_type, + const ClangASTType *args, + unsigned num_args, + bool is_variadic, + unsigned type_quals); + + ClangASTType + CreateFunctionType (const ClangASTType &result_type, + const ClangASTType *args, + unsigned num_args, + bool is_variadic, + unsigned type_quals) + { + return ClangASTContext::CreateFunctionType(getASTContext(), + result_type, + args, + num_args, + is_variadic, + type_quals); + } + + clang::ParmVarDecl * + CreateParameterDeclaration (const char *name, + const ClangASTType ¶m_type, + int storage); + + void + SetFunctionParameters (clang::FunctionDecl *function_decl, + clang::ParmVarDecl **params, + unsigned num_params); + + //------------------------------------------------------------------ + // Array Types + //------------------------------------------------------------------ + + ClangASTType + CreateArrayType (const ClangASTType &element_type, + size_t element_count, + bool is_vector); + + //------------------------------------------------------------------ + // Enumeration Types + //------------------------------------------------------------------ + ClangASTType + CreateEnumerationType (const char *name, + clang::DeclContext *decl_ctx, + const Declaration &decl, + const ClangASTType &integer_qual_type); + + //------------------------------------------------------------------ + // Floating point functions + //------------------------------------------------------------------ + + ClangASTType + GetFloatTypeFromBitSize (size_t bit_size) + { + return GetFloatTypeFromBitSize (getASTContext(), bit_size); + } + + static ClangASTType + GetFloatTypeFromBitSize (clang::ASTContext *ast, + size_t bit_size); +protected: + //------------------------------------------------------------------ + // Classes that inherit from ClangASTContext can see and modify these + //------------------------------------------------------------------ + std::string m_target_triple; + std::unique_ptr<clang::ASTContext> m_ast_ap; + std::unique_ptr<clang::LangOptions> m_language_options_ap; + std::unique_ptr<clang::FileManager> m_file_manager_ap; + std::unique_ptr<clang::FileSystemOptions> m_file_system_options_ap; + std::unique_ptr<clang::SourceManager> m_source_manager_ap; + std::unique_ptr<clang::DiagnosticsEngine> m_diagnostics_engine_ap; + std::unique_ptr<clang::DiagnosticConsumer> m_diagnostic_consumer_ap; + llvm::IntrusiveRefCntPtr<clang::TargetOptions> m_target_options_rp; + std::unique_ptr<clang::TargetInfo> m_target_info_ap; + std::unique_ptr<clang::IdentifierTable> m_identifier_table_ap; + std::unique_ptr<clang::SelectorTable> m_selector_table_ap; + std::unique_ptr<clang::Builtin::Context> m_builtins_ap; + CompleteTagDeclCallback m_callback_tag_decl; + CompleteObjCInterfaceDeclCallback m_callback_objc_decl; + void * m_callback_baton; + uint32_t m_pointer_byte_size; +private: + //------------------------------------------------------------------ + // For ClangASTContext only + //------------------------------------------------------------------ + ClangASTContext(const ClangASTContext&); + const ClangASTContext& operator=(const ClangASTContext&); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangASTContext_h_ diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h new file mode 100644 index 0000000..10df7da --- /dev/null +++ b/include/lldb/Symbol/ClangASTImporter.h @@ -0,0 +1,371 @@ +//===-- ClangASTImporter.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_ClangASTImporter_h_ +#define liblldb_ClangASTImporter_h_ + +#include <map> +#include <set> + +#include "lldb/lldb-types.h" +#include "clang/AST/ASTImporter.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" + +namespace lldb_private { + +class ClangASTMetrics +{ +public: + static void DumpCounters (Log *log); + static void ClearLocalCounters () + { + local_counters = { 0, 0, 0, 0, 0, 0 }; + } + + static void RegisterVisibleQuery () + { + ++global_counters.m_visible_query_count; + ++local_counters.m_visible_query_count; + } + + static void RegisterLexicalQuery () + { + ++global_counters.m_lexical_query_count; + ++local_counters.m_lexical_query_count; + } + + static void RegisterLLDBImport () + { + ++global_counters.m_lldb_import_count; + ++local_counters.m_lldb_import_count; + } + + static void RegisterClangImport () + { + ++global_counters.m_clang_import_count; + ++local_counters.m_clang_import_count; + } + + static void RegisterDeclCompletion () + { + ++global_counters.m_decls_completed_count; + ++local_counters.m_decls_completed_count; + } + + static void RegisterRecordLayout () + { + ++global_counters.m_record_layout_count; + ++local_counters.m_record_layout_count; + } + +private: + struct Counters + { + uint64_t m_visible_query_count; + uint64_t m_lexical_query_count; + uint64_t m_lldb_import_count; + uint64_t m_clang_import_count; + uint64_t m_decls_completed_count; + uint64_t m_record_layout_count; + }; + + static Counters global_counters; + static Counters local_counters; + + static void DumpCounters (Log *log, Counters &counters); +}; + +class ClangASTImporter +{ +public: + ClangASTImporter () : + m_file_manager(clang::FileSystemOptions()) + { + } + + clang::QualType + CopyType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::QualType type); + + lldb::clang_type_t + CopyType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::clang_type_t type); + + clang::Decl * + CopyDecl (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::Decl *decl); + + lldb::clang_type_t + DeportType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::clang_type_t type); + + clang::Decl * + DeportDecl (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::Decl *decl); + + void + CompleteDecl (clang::Decl *decl); + + bool + CompleteTagDecl (clang::TagDecl *decl); + + bool + CompleteTagDeclWithOrigin (clang::TagDecl *decl, clang::TagDecl *origin); + + bool + CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl); + + bool + RequireCompleteType (clang::QualType type); + + bool + ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx) + { + DeclOrigin origin = GetDeclOrigin(decl); + + if (original_decl) + *original_decl = origin.decl; + + if (original_ctx) + *original_ctx = origin.ctx; + + return origin.Valid(); + } + + void + SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl); + + ClangASTMetadata * + GetDeclMetadata (const clang::Decl *decl); + + // + // Namespace maps + // + + typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap; + typedef std::shared_ptr<NamespaceMap> NamespaceMapSP; + + void RegisterNamespaceMap (const clang::NamespaceDecl *decl, + NamespaceMapSP &namespace_map); + + NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl); + + void BuildNamespaceMap (const clang::NamespaceDecl *decl); + + // + // Comleters for maps + // + + class MapCompleter + { + public: + virtual ~MapCompleter (); + + virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map, + const ConstString &name, + NamespaceMapSP &parent_map) const = 0; + }; + + void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer) + { + ASTContextMetadataSP context_md; + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter == m_metadata_map.end()) + { + context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); + m_metadata_map[dst_ctx] = context_md; + } + else + { + context_md = context_md_iter->second; + } + + context_md->m_map_completer = &completer; + } + + void ForgetDestination (clang::ASTContext *dst_ctx); + void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx); +private: + struct DeclOrigin + { + DeclOrigin () : + ctx(NULL), + decl(NULL) + { + } + + DeclOrigin (clang::ASTContext *_ctx, + clang::Decl *_decl) : + ctx(_ctx), + decl(_decl) + { + } + + DeclOrigin (const DeclOrigin &rhs) + { + ctx = rhs.ctx; + decl = rhs.decl; + } + + void operator= (const DeclOrigin &rhs) + { + ctx = rhs.ctx; + decl = rhs.decl; + } + + bool + Valid () + { + return (ctx != NULL || decl != NULL); + } + + clang::ASTContext *ctx; + clang::Decl *decl; + }; + + typedef std::map<const clang::Decl *, DeclOrigin> OriginMap; + + class Minion : public clang::ASTImporter + { + public: + Minion (ClangASTImporter &master, + clang::ASTContext *target_ctx, + clang::ASTContext *source_ctx) : + clang::ASTImporter(*target_ctx, + master.m_file_manager, + *source_ctx, + master.m_file_manager, + true /*minimal*/), + m_decls_to_deport(NULL), + m_decls_already_deported(NULL), + m_master(master), + m_source_ctx(source_ctx) + { + } + + // A call to "InitDeportWorkQueues" puts the minion into deport mode. + // In deport mode, every copied Decl that could require completion is + // recorded and placed into the decls_to_deport set. + // + // A call to "ExecuteDeportWorkQueues" completes all the Decls that + // are in decls_to_deport, adding any Decls it sees along the way that + // it hasn't already deported. It proceeds until decls_to_deport is + // empty. + // + // These calls must be paired. Leaving a minion in deport mode or + // trying to start deport minion with a new pair of queues will result + // in an assertion failure. + + void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport, + std::set<clang::NamedDecl *> *decls_already_deported); + void ExecuteDeportWorkQueues (); + + void ImportDefinitionTo (clang::Decl *to, clang::Decl *from); + + clang::Decl *Imported (clang::Decl *from, clang::Decl *to); + + std::set<clang::NamedDecl *> *m_decls_to_deport; + std::set<clang::NamedDecl *> *m_decls_already_deported; + ClangASTImporter &m_master; + clang::ASTContext *m_source_ctx; + }; + + typedef std::shared_ptr<Minion> MinionSP; + typedef std::map<clang::ASTContext *, MinionSP> MinionMap; + typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap; + + struct ASTContextMetadata + { + ASTContextMetadata(clang::ASTContext *dst_ctx) : + m_dst_ctx (dst_ctx), + m_minions (), + m_origins (), + m_namespace_maps (), + m_map_completer (NULL) + { + } + + clang::ASTContext *m_dst_ctx; + MinionMap m_minions; + OriginMap m_origins; + + NamespaceMetaMap m_namespace_maps; + MapCompleter *m_map_completer; + }; + + typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP; + typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap; + + ContextMetadataMap m_metadata_map; + + ASTContextMetadataSP + GetContextMetadata (clang::ASTContext *dst_ctx) + { + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter == m_metadata_map.end()) + { + ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); + m_metadata_map[dst_ctx] = context_md; + return context_md; + } + else + { + return context_md_iter->second; + } + } + + ASTContextMetadataSP + MaybeGetContextMetadata (clang::ASTContext *dst_ctx) + { + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter != m_metadata_map.end()) + return context_md_iter->second; + else + return ASTContextMetadataSP(); + } + + MinionSP + GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx) + { + ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx); + + MinionMap &minions = context_md->m_minions; + MinionMap::iterator minion_iter = minions.find(src_ctx); + + if (minion_iter == minions.end()) + { + MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx)); + minions[src_ctx] = minion; + return minion; + } + else + { + return minion_iter->second; + } + } + + DeclOrigin + GetDeclOrigin (const clang::Decl *decl); + + clang::FileManager m_file_manager; +}; + +} + +#endif diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h new file mode 100644 index 0000000..d9e754e --- /dev/null +++ b/include/lldb/Symbol/ClangASTType.h @@ -0,0 +1,679 @@ +//===-- ClangASTType.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_ClangASTType_h_ +#define liblldb_ClangASTType_h_ + +#include <string> +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "clang/AST/Type.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A class that can carry around a clang ASTContext and a opaque clang +// QualType. A clang::QualType can be easily reconstructed from an +// opaque clang type and often the ASTContext is needed when doing +// various type related tasks, so this class allows both items to travel +// in a single very lightweight class that can be used. There are many +// static equivalents of the member functions that allow the ASTContext +// and the opaque clang QualType to be specified for ease of use and +// to avoid code duplication. +//---------------------------------------------------------------------- +class ClangASTType +{ +public: + enum { + eTypeHasChildren = (1u << 0), + eTypeHasValue = (1u << 1), + eTypeIsArray = (1u << 2), + eTypeIsBlock = (1u << 3), + eTypeIsBuiltIn = (1u << 4), + eTypeIsClass = (1u << 5), + eTypeIsCPlusPlus = (1u << 6), + eTypeIsEnumeration = (1u << 7), + eTypeIsFuncPrototype = (1u << 8), + eTypeIsMember = (1u << 9), + eTypeIsObjC = (1u << 10), + eTypeIsPointer = (1u << 11), + eTypeIsReference = (1u << 12), + eTypeIsStructUnion = (1u << 13), + eTypeIsTemplate = (1u << 14), + eTypeIsTypedef = (1u << 15), + eTypeIsVector = (1u << 16), + eTypeIsScalar = (1u << 17), + eTypeIsInteger = (1u << 18), + eTypeIsFloat = (1u << 19), + eTypeIsComplex = (1u << 20), + eTypeIsSigned = (1u << 21) + }; + + + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + ClangASTType (clang::ASTContext *ast_context, lldb::clang_type_t type) : + m_type (type), + m_ast (ast_context) + { + } + + ClangASTType (clang::ASTContext *ast_context, clang::QualType qual_type); + + ClangASTType (const ClangASTType &rhs) : + m_type (rhs.m_type), + m_ast (rhs.m_ast) + { + } + + ClangASTType () : + m_type (0), + m_ast (0) + { + } + + ~ClangASTType(); + + //---------------------------------------------------------------------- + // Operators + //---------------------------------------------------------------------- + + const ClangASTType & + operator= (const ClangASTType &rhs) + { + m_type = rhs.m_type; + m_ast = rhs.m_ast; + return *this; + } + + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + operator bool () const + { + return m_type != NULL && m_ast != NULL; + } + + bool + operator < (const ClangASTType &rhs) const + { + if (m_ast == rhs.m_ast) + return m_type < rhs.m_type; + return m_ast < rhs.m_ast; + } + + bool + IsValid () const + { + return m_type != NULL && m_ast != NULL; + } + + bool + IsArrayType (ClangASTType *element_type, + uint64_t *size, + bool *is_incomplete) const; + + bool + IsArrayOfScalarType () const; + + bool + IsAggregateType () const; + + bool + IsBeingDefined () const; + + bool + IsCharType () const; + + bool + IsCompleteType () const; + + bool + IsConst() const; + + bool + IsCStringType (uint32_t &length) const; + + bool + IsCXXClassType () const; + + bool + IsDefined() const; + + bool + IsFloatingPointType (uint32_t &count, bool &is_complex) const; + + bool + IsFunctionType (bool *is_variadic_ptr = NULL) const; + + bool + IsVariadicFunctionType () const; + + bool + IsFunctionPointerType () const; + + bool + IsIntegerType (bool &is_signed) const; + + bool + IsObjCClassType () const; + + bool + IsObjCClassTypeAndHasIVars (bool check_superclass) const; + + bool + IsObjCObjectOrInterfaceType () const; + + bool + IsObjCObjectPointerType (ClangASTType *target_type = NULL); + + bool + IsPolymorphicClass () const; + + bool + IsPossibleCPlusPlusDynamicType (ClangASTType *target_type = NULL) const + { + return IsPossibleDynamicType (target_type, true, false); + } + + bool + IsPossibleDynamicType (ClangASTType *target_type, // Can pass NULL + bool check_cplusplus, + bool check_objc) const; + + + bool + IsPointerToScalarType () const; + + bool + IsPointerType (ClangASTType *pointee_type = NULL) const; + + bool + IsPointerOrReferenceType (ClangASTType *pointee_type = NULL) const; + + bool + IsReferenceType (ClangASTType *pointee_type = NULL) const; + + bool + IsScalarType () const; + + bool + IsTypedefType () const; + + bool + IsVoidType () const; + + bool + GetCXXClassName (std::string &class_name) const; + + bool + GetObjCClassName (std::string &class_name); + + + //---------------------------------------------------------------------- + // Type Completion + //---------------------------------------------------------------------- + + bool + GetCompleteType () const; + + //---------------------------------------------------------------------- + // AST related queries + //---------------------------------------------------------------------- + + size_t + GetPointerByteSize () const; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + clang::ASTContext * + GetASTContext() const + { + return m_ast; + } + + ConstString + GetConstQualifiedTypeName () const; + + ConstString + GetConstTypeName () const; + + std::string + GetTypeName () const; + + uint32_t + GetTypeInfo (ClangASTType *pointee_or_element_clang_type = NULL) const; + + lldb::LanguageType + GetMinimumLanguage (); + + lldb::clang_type_t + GetOpaqueQualType() const + { + return m_type; + } + + lldb::TypeClass + GetTypeClass () const; + + void + SetClangType (clang::ASTContext *ast, lldb::clang_type_t type) + { + m_ast = ast; + m_type = type; + } + + void + SetClangType (clang::ASTContext *ast, clang::QualType qual_type); + + unsigned + GetTypeQualifiers() const; + + //---------------------------------------------------------------------- + // Creating related types + //---------------------------------------------------------------------- + + ClangASTType + AddConstModifier () const; + + ClangASTType + AddRestrictModifier () const; + + ClangASTType + AddVolatileModifier () const; + + // Using the current type, create a new typedef to that type using "typedef_name" + // as the name and "decl_ctx" as the decl context. + ClangASTType + CreateTypedefType (const char *typedef_name, + clang::DeclContext *decl_ctx) const; + + ClangASTType + GetArrayElementType (uint64_t& stride) const; + + ClangASTType + GetCanonicalType () const; + + ClangASTType + GetFullyUnqualifiedType () const; + + // Returns -1 if this isn't a function of if the fucntion doesn't have a prototype + // Returns a value >= 0 if there is a prototype. + int + GetFunctionArgumentCount () const; + + ClangASTType + GetFunctionArgumentTypeAtIndex (size_t idx); + + ClangASTType + GetFunctionReturnType () const; + + ClangASTType + GetLValueReferenceType () const; + + ClangASTType + GetNonReferenceType () const; + + ClangASTType + GetPointeeType () const; + + ClangASTType + GetPointerType () const; + + ClangASTType + GetRValueReferenceType () const; + + // If the current object represents a typedef type, get the underlying type + ClangASTType + GetTypedefedType () const; + + ClangASTType + RemoveFastQualifiers () const; + + //---------------------------------------------------------------------- + // Create related types using the current type's AST + //---------------------------------------------------------------------- + ClangASTType + GetBasicTypeFromAST (lldb::BasicType basic_type) const; + + //---------------------------------------------------------------------- + // Exploring the type + //---------------------------------------------------------------------- + + uint64_t + GetByteSize () const; + + uint64_t + GetBitSize () const; + + lldb::Encoding + GetEncoding (uint64_t &count) const; + + lldb::Format + GetFormat () const; + + size_t + GetTypeBitAlign () const; + + uint32_t + GetNumChildren (bool omit_empty_base_classes) const; + + lldb::BasicType + GetBasicTypeEnumeration () const; + + static lldb::BasicType + GetBasicTypeEnumeration (const ConstString &name); + + uint32_t + GetNumDirectBaseClasses () const; + + uint32_t + GetNumVirtualBaseClasses () const; + + uint32_t + GetNumFields () const; + + ClangASTType + GetDirectBaseClassAtIndex (size_t idx, + uint32_t *bit_offset_ptr) const; + + ClangASTType + GetVirtualBaseClassAtIndex (size_t idx, + uint32_t *bit_offset_ptr) const; + + ClangASTType + GetFieldAtIndex (size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) const; + + uint32_t + GetIndexOfFieldWithName (const char* name, + ClangASTType* field_clang_type = NULL, + uint64_t *bit_offset_ptr = NULL, + uint32_t *bitfield_bit_size_ptr = NULL, + bool *is_bitfield_ptr = NULL) const; + + uint32_t + GetNumPointeeChildren () const; + + ClangASTType + GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, + const char *parent_name, + size_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, + uint32_t &child_bitfield_bit_size, + uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, + bool &child_is_deref_of_parent) const; + + // Lookup a child given a name. This function will match base class names + // and member member names in "clang_type" only, not descendants. + uint32_t + GetIndexOfChildWithName (const char *name, + bool omit_empty_base_classes) const; + + // Lookup a child member given a name. This function will match member names + // only and will descend into "clang_type" children in search for the first + // member in this class, or any base class that matches "name". + // TODO: Return all matches for a given name by returning a vector<vector<uint32_t>> + // so we catch all names that match a given child name, not just the first. + size_t + GetIndexOfChildMemberWithName (const char *name, + bool omit_empty_base_classes, + std::vector<uint32_t>& child_indexes) const; + + size_t + GetNumTemplateArguments () const; + + ClangASTType + GetTemplateArgument (size_t idx, + lldb::TemplateArgumentKind &kind) const; + + + //---------------------------------------------------------------------- + // Modifying RecordType + //---------------------------------------------------------------------- + clang::FieldDecl * + AddFieldToRecordType (const char *name, + const ClangASTType &field_type, + lldb::AccessType access, + uint32_t bitfield_bit_size); + + void + BuildIndirectFields (); + + clang::VarDecl * + AddVariableToRecordType (const char *name, + const ClangASTType &var_type, + lldb::AccessType access); + + clang::CXXMethodDecl * + AddMethodToCXXRecordType (const char *name, + const ClangASTType &method_type, + lldb::AccessType access, + bool is_virtual, + bool is_static, + bool is_inline, + bool is_explicit, + bool is_attr_used, + bool is_artificial); + + // C++ Base Classes + clang::CXXBaseSpecifier * + CreateBaseClassSpecifier (lldb::AccessType access, + bool is_virtual, + bool base_of_class); + + static void + DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, + unsigned num_base_classes); + + bool + SetBaseClassesForClassType (clang::CXXBaseSpecifier const * const *base_classes, + unsigned num_base_classes); + + + bool + SetObjCSuperClass (const ClangASTType &superclass_clang_type); + + bool + AddObjCClassProperty (const char *property_name, + const ClangASTType &property_clang_type, + clang::ObjCIvarDecl *ivar_decl, + const char *property_setter_name, + const char *property_getter_name, + uint32_t property_attributes, + ClangASTMetadata *metadata); + + clang::ObjCMethodDecl * + AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]") + const ClangASTType &method_clang_type, + lldb::AccessType access, + bool is_artificial); + + clang::DeclContext * + GetDeclContextForType () const; + + + bool + SetDefaultAccessForRecordFields (int default_accessibility, + int *assigned_accessibilities, + size_t num_assigned_accessibilities); + + bool + SetHasExternalStorage (bool has_extern); + + + //------------------------------------------------------------------ + // clang::TagType + //------------------------------------------------------------------ + + bool + SetTagTypeKind (int kind) const; + + //------------------------------------------------------------------ + // Tag Declarations + //------------------------------------------------------------------ + bool + StartTagDeclarationDefinition (); + + bool + CompleteTagDeclarationDefinition (); + + //---------------------------------------------------------------------- + // Modifying Enumeration types + //---------------------------------------------------------------------- + bool + AddEnumerationValueToEnumerationType (const ClangASTType &enumerator_qual_type, + const Declaration &decl, + const char *name, + int64_t enum_value, + uint32_t enum_value_bit_size); + + + + ClangASTType + GetEnumerationIntegerType () const; + + + //------------------------------------------------------------------ + // Pointers & References + //------------------------------------------------------------------ + + // Call this function using the class type when you want to make a + // member pointer type to pointee_type. + ClangASTType + CreateMemberPointerType (const ClangASTType &pointee_type) const; + + + // Converts "s" to a floating point value and place resulting floating + // point bytes in the "dst" buffer. + size_t + ConvertStringToFloatValue (const char *s, + uint8_t *dst, + size_t dst_size) const; + //---------------------------------------------------------------------- + // Dumping types + //---------------------------------------------------------------------- + void + DumpValue (ExecutionContext *exe_ctx, + Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool show_types, + bool show_summary, + bool verbose, + uint32_t depth); + + bool + DumpTypeValue (Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope); + + void + DumpSummary (ExecutionContext *exe_ctx, + Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size); + + void + DumpTypeDescription () const; // Dump to stdout + + void + DumpTypeDescription (Stream *s) const; + + bool + GetValueAsScalar (const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + Scalar &value) const; + + bool + SetValueFromScalar (const Scalar &value, + Stream &strm); + + bool + ReadFromMemory (ExecutionContext *exe_ctx, + lldb::addr_t addr, + AddressType address_type, + DataExtractor &data); + + bool + WriteToMemory (ExecutionContext *exe_ctx, + lldb::addr_t addr, + AddressType address_type, + StreamString &new_value); + + + clang::RecordDecl * + GetAsRecordDecl () const; + + clang::CXXRecordDecl * + GetAsCXXRecordDecl () const; + + clang::ObjCInterfaceDecl * + GetAsObjCInterfaceDecl () const; + + void + Clear() + { + m_type = NULL; + m_ast = NULL; + } + + clang::QualType + GetQualType () const + { + if (m_type) + return clang::QualType::getFromOpaquePtr(m_type); + return clang::QualType(); + } + clang::QualType + GetCanonicalQualType () const + { + if (m_type) + return clang::QualType::getFromOpaquePtr(m_type).getCanonicalType(); + return clang::QualType(); + } + +private: + lldb::clang_type_t m_type; + clang::ASTContext *m_ast; + +}; + +bool operator == (const ClangASTType &lhs, const ClangASTType &rhs); +bool operator != (const ClangASTType &lhs, const ClangASTType &rhs); + + +} // namespace lldb_private + +#endif // #ifndef liblldb_ClangASTType_h_ diff --git a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h new file mode 100644 index 0000000..0c81211 --- /dev/null +++ b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h @@ -0,0 +1,171 @@ +//===-- ClangExternalASTSourceCallbacks.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_ClangExternalASTSourceCallbacks_h_ +#define liblldb_ClangExternalASTSourceCallbacks_h_ + +// C Includes +// C++ Includes +#include <string> +#include <vector> +#include <stdint.h> + +// Other libraries and framework includes +#include "clang/AST/CharUnits.h" + +// Project includes +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" + +namespace lldb_private { + +class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon +{ +public: + + typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); + typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *); + typedef void (*FindExternalVisibleDeclsByNameCallback)(void *baton, const clang::DeclContext *DC, clang::DeclarationName Name, llvm::SmallVectorImpl <clang::NamedDecl *> *results); + typedef bool (*LayoutRecordTypeCallback)(void *baton, + const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets); + + ClangExternalASTSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, + CompleteObjCInterfaceDeclCallback objc_decl_callback, + FindExternalVisibleDeclsByNameCallback find_by_name_callback, + LayoutRecordTypeCallback layout_record_type_callback, + void *callback_baton) : + m_callback_tag_decl (tag_decl_callback), + m_callback_objc_decl (objc_decl_callback), + m_callback_find_by_name (find_by_name_callback), + m_callback_layout_record_type (layout_record_type_callback), + m_callback_baton (callback_baton) + { + } + + //------------------------------------------------------------------ + // clang::ExternalASTSource + //------------------------------------------------------------------ + + virtual clang::Decl * + GetExternalDecl (uint32_t ID) + { + // This method only needs to be implemented if the AST source ever + // passes back decl sets as VisibleDeclaration objects. + return 0; + } + + virtual clang::Stmt * + GetExternalDeclStmt (uint64_t Offset) + { + // This operation is meant to be used via a LazyOffsetPtr. It only + // needs to be implemented if the AST source uses methods like + // FunctionDecl::setLazyBody when building decls. + return 0; + } + + virtual clang::Selector + GetExternalSelector (uint32_t ID) + { + // This operation only needs to be implemented if the AST source + // returns non-zero for GetNumKnownSelectors(). + return clang::Selector(); + } + + virtual uint32_t + GetNumExternalSelectors() + { + return 0; + } + + virtual clang::CXXBaseSpecifier * + GetExternalCXXBaseSpecifiers(uint64_t Offset) + { + return NULL; + } + + virtual void + MaterializeVisibleDecls (const clang::DeclContext *decl_ctx) + { + return; + } + + virtual clang::ExternalLoadResult + FindExternalLexicalDecls (const clang::DeclContext *decl_ctx, + bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl<clang::Decl*> &decls) + { + // This is used to support iterating through an entire lexical context, + // which isn't something the debugger should ever need to do. + return clang::ELR_Failure; + } + + virtual bool + FindExternalVisibleDeclsByName (const clang::DeclContext *decl_ctx, + clang::DeclarationName decl_name); + + virtual void + CompleteType (clang::TagDecl *tag_decl); + + virtual void + CompleteType (clang::ObjCInterfaceDecl *objc_decl); + + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets); + void + SetExternalSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, + CompleteObjCInterfaceDeclCallback objc_decl_callback, + FindExternalVisibleDeclsByNameCallback find_by_name_callback, + LayoutRecordTypeCallback layout_record_type_callback, + void *callback_baton) + { + m_callback_tag_decl = tag_decl_callback; + m_callback_objc_decl = objc_decl_callback; + m_callback_find_by_name = find_by_name_callback; + m_callback_layout_record_type = layout_record_type_callback; + m_callback_baton = callback_baton; + } + + void + RemoveExternalSourceCallbacks (void *callback_baton) + { + if (callback_baton == m_callback_baton) + { + m_callback_tag_decl = NULL; + m_callback_objc_decl = NULL; + m_callback_find_by_name = NULL; + m_callback_layout_record_type = NULL; + } + } + +protected: + //------------------------------------------------------------------ + // Classes that inherit from ClangExternalASTSourceCallbacks can see and modify these + //------------------------------------------------------------------ + CompleteTagDeclCallback m_callback_tag_decl; + CompleteObjCInterfaceDeclCallback m_callback_objc_decl; + FindExternalVisibleDeclsByNameCallback m_callback_find_by_name; + LayoutRecordTypeCallback m_callback_layout_record_type; + void * m_callback_baton; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExternalASTSourceCallbacks_h_ diff --git a/include/lldb/Symbol/ClangExternalASTSourceCommon.h b/include/lldb/Symbol/ClangExternalASTSourceCommon.h new file mode 100644 index 0000000..72d77e7 --- /dev/null +++ b/include/lldb/Symbol/ClangExternalASTSourceCommon.h @@ -0,0 +1,188 @@ +//===-- ClangExternalASTSourceCommon.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_ClangExternalASTSourceCommon_h +#define liblldb_ClangExternalASTSourceCommon_h + +// Clang headers like to use NDEBUG inside of them to enable/disable debug +// releated features using "#ifndef NDEBUG" preprocessor blocks to do one thing +// or another. This is bad because it means that if clang was built in release +// mode, it assumes that you are building in release mode which is not always +// the case. You can end up with functions that are defined as empty in header +// files when NDEBUG is not defined, and this can cause link errors with the +// clang .a files that you have since you might be missing functions in the .a +// file. So we have to define NDEBUG when including clang headers to avoid any +// mismatches. This is covered by rdar://problem/8691220 + +#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF) +#define LLDB_DEFINED_NDEBUG_FOR_CLANG +#define NDEBUG +// Need to include assert.h so it is as clang would expect it to be (disabled) +#include <assert.h> +#endif + +#include "clang/AST/ExternalASTSource.h" + +#ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG +#undef NDEBUG +#undef LLDB_DEFINED_NDEBUG_FOR_CLANG +// Need to re-include assert.h so it is as _we_ would expect it to be (enabled) +#include <assert.h> +#endif + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/dwarf.h" + +namespace lldb_private { + +class ClangASTMetadata +{ +public: + ClangASTMetadata () : + m_user_id(0), + m_union_is_user_id(false), + m_union_is_isa_ptr(false), + m_has_object_ptr(false), + m_is_self (false), + m_is_dynamic_cxx (true) + { + } + + bool + GetIsDynamicCXXType () const + { + return m_is_dynamic_cxx; + } + + void + SetIsDynamicCXXType (bool b) + { + m_is_dynamic_cxx = b; + } + + void + SetUserID (lldb::user_id_t user_id) + { + m_user_id = user_id; + m_union_is_user_id = true; + m_union_is_isa_ptr = false; + } + + lldb::user_id_t + GetUserID () const + { + if (m_union_is_user_id) + return m_user_id; + else + return LLDB_INVALID_UID; + } + + void + SetISAPtr (uint64_t isa_ptr) + { + m_isa_ptr = isa_ptr; + m_union_is_user_id = false; + m_union_is_isa_ptr = true; + } + + uint64_t + GetISAPtr () const + { + if (m_union_is_isa_ptr) + return m_isa_ptr; + else + return 0; + } + + void + SetObjectPtrName(const char *name) + { + m_has_object_ptr = true; + if (strcmp (name, "self") == 0) + m_is_self = true; + else if (strcmp (name, "this") == 0) + m_is_self = false; + else + m_has_object_ptr = false; + } + + lldb::LanguageType + GetObjectPtrLanguage () const + { + if (m_has_object_ptr) + { + if (m_is_self) + return lldb::eLanguageTypeObjC; + else + return lldb::eLanguageTypeC_plus_plus; + } + return lldb::eLanguageTypeUnknown; + + } + const char * + GetObjectPtrName() const + { + if (m_has_object_ptr) + { + if (m_is_self) + return "self"; + else + return "this"; + } + else + return NULL; + } + + bool + HasObjectPtr() const + { + return m_has_object_ptr; + } + + void + Dump (Stream *s); + +private: + union + { + lldb::user_id_t m_user_id; + uint64_t m_isa_ptr; + }; + bool m_union_is_user_id : 1, + m_union_is_isa_ptr : 1, + m_has_object_ptr : 1, + m_is_self : 1, + m_is_dynamic_cxx : 1; + +}; + +class ClangExternalASTSourceCommon : public clang::ExternalASTSource +{ +public: + ClangExternalASTSourceCommon(); + ~ClangExternalASTSourceCommon(); + + virtual ClangASTMetadata *GetMetadata(const void *object); + virtual void SetMetadata(const void *object, ClangASTMetadata &metadata); + virtual bool HasMetadata(const void *object); +private: + typedef llvm::DenseMap<const void *, ClangASTMetadata> MetadataMap; + + MetadataMap m_metadata; + uint64_t m_magic; ///< Because we don't have RTTI, we must take it + ///< on faith that any valid ExternalASTSource that + ///< we try to use the *Metadata APIs on inherits + ///< from ClangExternalASTSourceCommon. This magic + ///< number exists to enforce that. +}; + +} + +#endif diff --git a/include/lldb/Symbol/ClangNamespaceDecl.h b/include/lldb/Symbol/ClangNamespaceDecl.h new file mode 100644 index 0000000..d10ab2a --- /dev/null +++ b/include/lldb/Symbol/ClangNamespaceDecl.h @@ -0,0 +1,103 @@ +//===-- ClangNamespaceDecl.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_ClangNamespaceDecl_h_ +#define liblldb_ClangNamespaceDecl_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { + +class ClangNamespaceDecl +{ +public: + ClangNamespaceDecl () : + m_ast (NULL), + m_namespace_decl (NULL) + { + } + + ClangNamespaceDecl (clang::ASTContext *ast, clang::NamespaceDecl *namespace_decl) : + m_ast (ast), + m_namespace_decl (namespace_decl) + { + } + + ClangNamespaceDecl (const ClangNamespaceDecl &rhs) : + m_ast (rhs.m_ast), + m_namespace_decl (rhs.m_namespace_decl) + { + } + + const ClangNamespaceDecl & + operator = (const ClangNamespaceDecl &rhs) + { + m_ast = rhs.m_ast; + m_namespace_decl = rhs.m_namespace_decl; + return *this; + } + + //------------------------------------------------------------------ + /// Convert to bool operator. + /// + /// This allows code to check a ClangNamespaceDecl object to see if + /// it contains a valid namespace decl using code such as: + /// + /// @code + /// ClangNamespaceDecl ns_decl(...); + /// if (ns_decl) + /// { ... + /// @endcode + /// + /// @return + /// /b True this object contains a valid namespace decl, \b + /// false otherwise. + //------------------------------------------------------------------ + operator bool() const + { + return m_ast != NULL && m_namespace_decl != NULL; + } + + clang::ASTContext * + GetASTContext() const + { + return m_ast; + } + + void + SetASTContext (clang::ASTContext *ast) + { + m_ast = ast; + } + + clang::NamespaceDecl * + GetNamespaceDecl () const + { + return m_namespace_decl; + } + + void + SetNamespaceDecl (clang::NamespaceDecl *namespace_decl) + { + m_namespace_decl = namespace_decl; + } + + std::string + GetQualifiedName () const; + +protected: + clang::ASTContext *m_ast; + clang::NamespaceDecl *m_namespace_decl; +}; + + +} // namespace lldb_private + +#endif // #ifndef liblldb_ClangNamespaceDecl_h_ diff --git a/include/lldb/Symbol/CompileUnit.h b/include/lldb/Symbol/CompileUnit.h new file mode 100644 index 0000000..5de9367 --- /dev/null +++ b/include/lldb/Symbol/CompileUnit.h @@ -0,0 +1,422 @@ +//===-- CompileUnit.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_CompUnit_h_ +#define liblldb_CompUnit_h_ + +#include "lldb/lldb-enumerations.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/UserID.h" + +namespace lldb_private { +//---------------------------------------------------------------------- +/// @class CompileUnit CompileUnit.h "lldb/Symbol/CompileUnit.h" +/// @brief A class that describes a compilation unit. +/// +/// A representation of a compilation unit, or compiled source file. +/// The UserID of the compile unit is specified by the SymbolFile +/// plug-in and can have any value as long as the value is unique +/// within the Module that owns this compile units. +/// +/// Each compile unit has a list of functions, global and static +/// variables, support file list (include files and inlined source +/// files), and a line table. +//---------------------------------------------------------------------- +class CompileUnit : + public std::enable_shared_from_this<CompileUnit>, + public ModuleChild, + public FileSpec, + public UserID, + public SymbolContextScope +{ +public: + //------------------------------------------------------------------ + /// Construct with a module, path, UID and language. + /// + /// Initialize the compile unit given the owning \a module, a path + /// to convert into a FileSpec, the SymbolFile plug-in supplied + /// \a uid, and the source language type. + /// + /// @param[in] module + /// The parent module that owns this compile unit. This value + /// must be a valid pointer value. + /// + /// @param[in] user_data + /// User data where the SymbolFile parser can store data. + /// + /// @param[in] pathname + /// The path to the source file for this compile unit. + /// + /// @param[in] uid + /// The user ID of the compile unit. This value is supplied by + /// the SymbolFile plug-in and should be a value that allows + /// the SymbolFile plug-in to easily locate and parse additional + /// information for the compile unit. + /// + /// @param[in] language + /// A language enumeration type that describes the main language + /// of this compile unit. + /// + /// @see lldb::LanguageType + //------------------------------------------------------------------ + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language); + + //------------------------------------------------------------------ + /// Construct with a module, file spec, UID and language. + /// + /// Initialize the compile unit given the owning \a module, a path + /// to convert into a FileSpec, the SymbolFile plug-in supplied + /// \a uid, and the source language type. + /// + /// @param[in] module + /// The parent module that owns this compile unit. This value + /// must be a valid pointer value. + /// + /// @param[in] user_data + /// User data where the SymbolFile parser can store data. + /// + /// @param[in] file_spec + /// The file specification for the source file of this compile + /// unit. + /// + /// @param[in] uid + /// The user ID of the compile unit. This value is supplied by + /// the SymbolFile plug-in and should be a value that allows + /// the plug-in to easily locate and parse + /// additional information for the compile unit. + /// + /// @param[in] language + /// A language enumeration type that describes the main language + /// of this compile unit. + /// + /// @see lldb::LanguageType + //------------------------------------------------------------------ + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual + ~CompileUnit(); + + //------------------------------------------------------------------ + /// Add a function to this compile unit. + /// + /// Typically called by the SymbolFile plug-ins as they partially + /// parse the debug information. + /// + /// @param[in] function_sp + /// A shared pointer to the a Function object. + //------------------------------------------------------------------ + void + AddFunction(lldb::FunctionSP& function_sp); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext(SymbolContext* sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual CompileUnit * + CalculateSymbolContextCompileUnit (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext(Stream *s); + + lldb::LanguageType + GetLanguage(); + + void + SetLanguage(lldb::LanguageType language) + { + m_flags.Set(flagsParsedLanguage); + m_language = language; + } + + void + GetDescription(Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Get a shared pointer to a function in this compile unit by + /// index. + /// + /// Typically called when iterating though all functions in a + /// compile unit after all functions have been parsed. This provides + /// raw access to the function shared pointer list and will not + /// cause the SymbolFile plug-in to parse any unparsed functions. + /// + /// @param[in] idx + /// An index into the function list. + /// + /// @return + /// A shared pointer to a function that might contain a NULL + /// Function class pointer. + //------------------------------------------------------------------ + lldb::FunctionSP + GetFunctionAtIndex (size_t idx); + + //------------------------------------------------------------------ + /// Dump the compile unit contents to the stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] show_context + /// If \b true, variables will dump their symbol context + /// information. + //------------------------------------------------------------------ + void + Dump (Stream *s, bool show_context) const; + + //------------------------------------------------------------------ + /// Find the line entry by line and optional inlined file spec. + /// + /// Finds the first line entry that has an index greater than + /// \a start_idx that matches \a line. If \a file_spec_ptr + /// is NULL, then the search matches line entries whose file matches + /// the file for the compile unit. If \a file_spec_ptr is + /// not NULL, line entries must match the specified file spec (for + /// inlined line table entries). + /// + /// Multiple calls to this function can find all entries that match + /// a given file and line by starting with \a start_idx equal to zero, + /// and calling this function back with the return valeu + 1. + /// + /// @param[in] start_idx + /// The zero based index at which to start looking for matches. + /// + /// @param[in] line + /// The line number to search for. + /// + /// @param[in] file_spec_ptr + /// If non-NULL search for entries that match this file spec, + /// else if NULL, search for line entries that match the compile + /// unit file. + /// + /// @param[in] exact + /// If \btrue match only if there is a line table entry for this line number. + /// If \bfalse, find the line table entry equal to or after this line number. + /// + /// @param[out] line_entry + /// If non-NULL, a copy of the line entry that was found. + /// + /// @return + /// The zero based index of a matching line entry, or UINT32_MAX + /// if no matching line entry is found. + //------------------------------------------------------------------ + uint32_t + FindLineEntry (uint32_t start_idx, + uint32_t line, + const FileSpec* file_spec_ptr, + bool exact, + LineEntry *line_entry); + + //------------------------------------------------------------------ + /// Get the line table for the compile unit. + /// + /// Called by clients and the SymbolFile plug-in. The SymbolFile + /// plug-ins use this function to determine if the line table has + /// be parsed yet. Clients use this function to get the line table + /// from a compile unit. + /// + /// @return + /// The line table object pointer, or NULL if this line table + /// hasn't been parsed yet. + //------------------------------------------------------------------ + LineTable* + GetLineTable (); + + //------------------------------------------------------------------ + /// Get the compile unit's support file list. + /// + /// The support file list is used by the line table, and any objects + /// that have valid Declaration objects. + /// + /// @return + /// A support file list object. + //------------------------------------------------------------------ + FileSpecList& + GetSupportFiles (); + + //------------------------------------------------------------------ + /// Get the SymbolFile plug-in user data. + /// + /// SymbolFile plug-ins can store user data to internal state or + /// objects to quickly allow them to parse more information for a + /// given object. + /// + /// @return + /// The user data stored with the CompileUnit when it was + /// constructed. + //------------------------------------------------------------------ + void * + GetUserData () const; + + //------------------------------------------------------------------ + /// Get the variable list for a compile unit. + /// + /// Called by clients to get the variable list for a compile unit. + /// The variable list will contain all global and static variables + /// that were defined at the compile unit level. + /// + /// @param[in] can_create + /// If \b true, the variable list will be parsed on demand. If + /// \b false, the current variable list will be returned even + /// if it contains a NULL VariableList object (typically + /// called by dumping routines that want to display only what + /// has currently been parsed). + /// + /// @return + /// A shared pointer to a variable list, that can contain NULL + /// VariableList pointer if there are no global or static + /// variables. + //------------------------------------------------------------------ + lldb::VariableListSP + GetVariableList (bool can_create); + + //------------------------------------------------------------------ + /// Finds a function by user ID. + /// + /// Typically used by SymbolFile plug-ins when partially parsing + /// the debug information to see if the function has been parsed + /// yet. + /// + /// @param[in] uid + /// The user ID of the function to find. This value is supplied + /// by the SymbolFile plug-in and should be a value that + /// allows the plug-in to easily locate and parse additional + /// information in the function. + /// + /// @return + /// A shared pointer to the function object that might contain + /// a NULL Function pointer. + //------------------------------------------------------------------ + lldb::FunctionSP + FindFunctionByUID (lldb::user_id_t uid); + + //------------------------------------------------------------------ + /// Set the line table for the compile unit. + /// + /// Called by the SymbolFile plug-in when if first parses the line + /// table and hands ownership of the line table to this object. The + /// compile unit owns the line table object and will delete the + /// object when it is deleted. + /// + /// @param[in] line_table + /// A line table object pointer that this object now owns. + //------------------------------------------------------------------ + void + SetLineTable(LineTable* line_table); + + //------------------------------------------------------------------ + /// Set accessor for the variable list. + /// + /// Called by the SymbolFile plug-ins after they have parsed the + /// variable lists and are ready to hand ownership of the list over + /// to this object. + /// + /// @param[in] variable_list_sp + /// A shared pointer to a VariableList. + //------------------------------------------------------------------ + void + SetVariableList (lldb::VariableListSP& variable_list_sp); + + //------------------------------------------------------------------ + /// Resolve symbol contexts by file and line. + /// + /// Given a file in \a file_spec, and a line number, find all + /// instances and append them to the supplied symbol context list + /// \a sc_list. + /// + /// @param[in] file_spec + /// A file specification. If \a file_spec contains no directory + /// information, only the basename will be used when matching + /// contexts. If the directory in \a file_spec is valid, a + /// complete file specification match will be performed. + /// + /// @param[in] line + /// The line number to match against the compile unit's line + /// tables. + /// + /// @param[in] check_inlines + /// If \b true this function will also match any inline + /// file and line matches. If \b false, the compile unit's + /// file specification must match \a file_spec for any matches + /// to be returned. + /// + /// @param[in] exact + /// If true, only resolve the context if \a line exists in the line table. + /// If false, resolve the context to the closest line greater than \a line + /// in the line table. + /// + /// @param[in] resolve_scope + /// For each matching line entry, this bitfield indicates what + /// values within each SymbolContext that gets added to \a + /// sc_list will be resolved. See the SymbolContext::Scope + /// enumeration for a list of all available bits that can be + /// resolved. Only SymbolContext entries that can be resolved + /// using a LineEntry base address will be able to be resolved. + /// + /// @param[out] sc_list + /// A SymbolContext list class that willl get any matching + /// entries appended to. + /// + /// @return + /// The number of new matches that were added to \a sc_list. + /// + /// @see enum SymbolContext::Scope + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContext (const FileSpec& file_spec, + uint32_t line, + bool check_inlines, + bool exact, + uint32_t resolve_scope, + SymbolContextList &sc_list); + + +protected: + void *m_user_data; ///< User data for the SymbolFile parser to store information into. + lldb::LanguageType m_language; ///< The programming language enumeration value. + Flags m_flags; ///< Compile unit flags that help with partial parsing. + std::vector<lldb::FunctionSP> m_functions; ///< The sparsely populated list of shared pointers to functions + ///< that gets populated as functions get partially parsed. + FileSpecList m_support_files; ///< Files associated with this compile unit's line table and declarations. + std::unique_ptr<LineTable> m_line_table_ap; ///< Line table that will get parsed on demand. + lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand. + +private: + enum + { + flagsParsedAllFunctions = (1u << 0), ///< Have we already parsed all our functions + flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics? + flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit? + flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already? + flagsParsedLanguage = (1u << 4) ///< Have we parsed the line table already? + }; + + DISALLOW_COPY_AND_ASSIGN (CompileUnit); +}; + +} // namespace lldb_private + +#endif // liblldb_CompUnit_h_ diff --git a/include/lldb/Symbol/DWARFCallFrameInfo.h b/include/lldb/Symbol/DWARFCallFrameInfo.h new file mode 100644 index 0000000..13a14f8 --- /dev/null +++ b/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -0,0 +1,150 @@ +//===-- DWARFCallFrameInfo.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_DWARFCallFrameInfo_h_ +#define liblldb_DWARFCallFrameInfo_h_ + +#include <map> + +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Flags.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/VMRange.h" +#include "lldb/Core/dwarf.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// DWARFCallFrameInfo is a class which can read eh_frame and DWARF +// Call Frame Information FDEs. It stores little information internally. +// Only two APIs are exported - one to find the high/low pc values +// of a function given a text address via the information in the +// eh_frame / debug_frame, and one to generate an UnwindPlan based +// on the FDE in the eh_frame / debug_frame section. + +class DWARFCallFrameInfo +{ +public: + + DWARFCallFrameInfo (ObjectFile& objfile, + lldb::SectionSP& section, + lldb::RegisterKind reg_kind, + bool is_eh_frame); + + ~DWARFCallFrameInfo(); + + // Locate an AddressRange that includes the provided Address in this + // object's eh_frame/debug_info + // Returns true if a range is found to cover that address. + bool + GetAddressRange (Address addr, AddressRange &range); + + // Return an UnwindPlan based on the call frame information encoded + // in the FDE of this DWARFCallFrameInfo section. + bool + GetUnwindPlan (Address addr, UnwindPlan& unwind_plan); + + typedef RangeVector<lldb::addr_t, uint32_t> FunctionAddressAndSizeVector; + + //------------------------------------------------------------------ + // Build a vector of file address and size for all functions in this Module + // based on the eh_frame FDE entries. + // + // The eh_frame information can be a useful source of file address and size of + // the functions in a Module. Often a binary's non-exported symbols are stripped + // before shipping so lldb won't know the start addr / size of many functions + // in the Module. But the eh_frame can help to give the addresses of these + // stripped symbols, at least. + // + // @param[out] function_info + // A vector provided by the caller is filled out. May be empty if no FDEs/no eh_frame + // is present in this Module. + + void + GetFunctionAddressAndSizeVector (FunctionAddressAndSizeVector &function_info); + +private: + enum + { + CFI_AUG_MAX_SIZE = 8, + CFI_HEADER_SIZE = 8 + }; + + struct CIE + { + dw_offset_t cie_offset; + uint8_t version; + char augmentation[CFI_AUG_MAX_SIZE]; // This is typically empty or very short. + uint32_t code_align; + int32_t data_align; + uint32_t return_addr_reg_num; + dw_offset_t inst_offset; // offset of CIE instructions in mCFIData + uint32_t inst_length; // length of CIE instructions in mCFIData + uint8_t ptr_encoding; + lldb_private::UnwindPlan::Row initial_row; + + CIE(dw_offset_t offset) : cie_offset(offset), version (-1), code_align (0), + data_align (0), return_addr_reg_num (LLDB_INVALID_REGNUM), inst_offset (0), + inst_length (0), ptr_encoding (0), initial_row() {} + }; + + typedef std::shared_ptr<CIE> CIESP; + + typedef std::map<off_t, CIESP> cie_map_t; + + // Start address (file address), size, offset of FDE location + // used for finding an FDE for a given File address; the start address field is + // an offset into an individual Module. + typedef RangeDataVector<lldb::addr_t, uint32_t, dw_offset_t> FDEEntryMap; + + bool + IsEHFrame() const; + + bool + GetFDEEntryByFileAddress (lldb::addr_t file_offset, FDEEntryMap::Entry& fde_entry); + + void + GetFDEIndex (); + + bool + FDEToUnwindPlan (uint32_t offset, Address startaddr, UnwindPlan& unwind_plan); + + const CIE* + GetCIE(dw_offset_t cie_offset); + + void + GetCFIData(); + + ObjectFile& m_objfile; + lldb::SectionSP m_section_sp; + lldb::RegisterKind m_reg_kind; + Flags m_flags; + cie_map_t m_cie_map; + + DataExtractor m_cfi_data; + bool m_cfi_data_initialized; // only copy the section into the DE once + + FDEEntryMap m_fde_index; + bool m_fde_index_initialized; // only scan the section for FDEs once + Mutex m_fde_index_mutex; // and isolate the thread that does it + + bool m_is_eh_frame; + + CIESP + ParseCIE (const uint32_t cie_offset); + +}; + +} // namespace lldb_private + +#endif // liblldb_DWARFCallFrameInfo_h_ diff --git a/include/lldb/Symbol/Declaration.h b/include/lldb/Symbol/Declaration.h new file mode 100644 index 0000000..f014571 --- /dev/null +++ b/include/lldb/Symbol/Declaration.h @@ -0,0 +1,278 @@ +//===-- Declaration.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_Declaration_h_ +#define liblldb_Declaration_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Host/FileSpec.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Declaration Declaration.h "lldb/Symbol/Declaration.h" +/// @brief A class that describes the declaration location of a +/// lldb object. +/// +/// The declarations include the file specification, line number, and +/// the column info and can help track where functions, blocks, inlined +/// functions, types, variables, any many other debug core objects were +/// declared. +//---------------------------------------------------------------------- +class Declaration +{ +public: + //------------------------------------------------------------------ + /// Default constructor. + //------------------------------------------------------------------ + Declaration () : + m_file (), + m_line (0) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column (0) +#endif + { + } + + + //------------------------------------------------------------------ + /// Construct with file specification, and optional line and column. + /// + /// @param[in] file_spec + /// The file specification that describes where this was + /// declared. + /// + /// @param[in] line + /// The line number that describes where this was declared. Set + /// to zero if there is no line number information. + /// + /// @param[in] column + /// The column number that describes where this was declared. + /// Set to zero if there is no column number information. + //------------------------------------------------------------------ + Declaration (const FileSpec& file_spec, uint32_t line = 0, uint32_t column = 0) : + m_file (file_spec), + m_line (line) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column (column) +#endif + { + } + + //------------------------------------------------------------------ + /// Construct with a reference to another Declaration object. + //------------------------------------------------------------------ + Declaration (const Declaration& rhs) : + m_file (rhs.m_file), + m_line (rhs.m_line) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column (rhs.m_column) +#endif + { + + } + + //------------------------------------------------------------------ + /// Construct with a pointer to another Declaration object. + //------------------------------------------------------------------ + Declaration(const Declaration* decl_ptr) : + m_file(), + m_line(0) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column(0) +#endif + { + if (decl_ptr) + *this = *decl_ptr; + } + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the file specification to be empty, and the line and column + /// to zero. + //------------------------------------------------------------------ + void + Clear () + { + m_file.Clear(); + m_line= 0; +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + m_column = 0; +#endif + } + + //------------------------------------------------------------------ + /// Compare two declaration objects. + /// + /// Compares the two file specifications from \a lhs and \a rhs. If + /// the file specifications are equal, then continue to compare the + /// line number and column numbers respectively. + /// + /// @param[in] lhs + /// The Left Hand Side const Declaration object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const Declaration object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + Compare (const Declaration& lhs, const Declaration& rhs); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s, bool show_fullpaths) const; + + bool + DumpStopContext (Stream *s, bool show_fullpaths) const; + //------------------------------------------------------------------ + /// Get accessor for the declaration column number. + /// + /// @return + /// Non-zero indicates a valid column number, zero indicates no + /// column information is available. + //------------------------------------------------------------------ + uint32_t + GetColumn () const + { +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + return m_column; +#else + return 0; +#endif + } + + //------------------------------------------------------------------ + /// Get accessor for file specification. + /// + /// @return + /// A reference to the file specification object. + //------------------------------------------------------------------ + FileSpec& + GetFile () + { + return m_file; + } + + //------------------------------------------------------------------ + /// Get const accessor for file specification. + /// + /// @return + /// A const reference to the file specification object. + //------------------------------------------------------------------ + const FileSpec& + GetFile () const + { + return m_file; + } + + //------------------------------------------------------------------ + /// Get accessor for the declaration line number. + /// + /// @return + /// Non-zero indicates a valid line number, zero indicates no + /// line information is available. + //------------------------------------------------------------------ + uint32_t + GetLine () const + { + return m_line; + } + + + bool + IsValid() const + { + return m_file && m_line != 0; + } + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + size_t + MemorySize () const; + + //------------------------------------------------------------------ + /// Set accessor for the declaration column number. + /// + /// @param[in] column + /// Non-zero indicates a valid column number, zero indicates no + /// column information is available. + //------------------------------------------------------------------ + void + SetColumn (uint32_t column) + { +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + m_column = col; +#endif + } + + //------------------------------------------------------------------ + /// Set accessor for the declaration file specification. + /// + /// @param[in] file_spec + /// The new declaration file specifciation. + //------------------------------------------------------------------ + void + SetFile (const FileSpec& file_spec) + { + m_file = file_spec; + } + + //------------------------------------------------------------------ + /// Set accessor for the declaration line number. + /// + /// @param[in] line + /// Non-zero indicates a valid line number, zero indicates no + /// line information is available. + //------------------------------------------------------------------ + void + SetLine (uint32_t line) + { + m_line = line; + } +protected: + //------------------------------------------------------------------ + /// Member variables. + //------------------------------------------------------------------ + FileSpec m_file; ///< The file specification that points to the + ///< source file where the declaration occurred. + uint32_t m_line; ///< Non-zero values indicates a valid line number, + ///< zero indicates no line number information is available. +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + uint32_t m_column; ///< Non-zero values indicates a valid column number, + ///< zero indicates no column information is available. +#endif +}; + +bool +operator == (const Declaration &lhs, const Declaration &rhs); + +} // namespace lldb_private + +#endif // liblldb_Declaration_h_ diff --git a/include/lldb/Symbol/FuncUnwinders.h b/include/lldb/Symbol/FuncUnwinders.h new file mode 100644 index 0000000..fa48dc2 --- /dev/null +++ b/include/lldb/Symbol/FuncUnwinders.h @@ -0,0 +1,106 @@ +#ifndef liblldb_FuncUnwinders_h +#define liblldb_FuncUnwinders_h + +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class UnwindTable; + +class FuncUnwinders +{ +public: + // FuncUnwinders objects are used to track UnwindPlans for a function + // (named or not - really just an address range) + + // We'll record three different UnwindPlans for each address range: + // 1. Unwinding from a call site (a valid exception throw location) + // This is often sourced from the eh_frame exception handling info + // 2. Unwinding from a non-call site (any location in the function) + // This is often done by analyzing the function prologue assembly + // langauge instructions + // 3. A fast unwind method for this function which only retrieves a + // limited set of registers necessary to walk the stack + // 4. An architectural default unwind plan when none of the above are + // available for some reason. + + // Additionally, FuncUnwinds object can be asked where the prologue + // instructions are finished for migrating breakpoints past the + // stack frame setup instructions when we don't have line table information. + + FuncUnwinders (lldb_private::UnwindTable& unwind_table, lldb_private::UnwindAssembly *assembly_profiler, AddressRange range); + + ~FuncUnwinders (); + + // current_offset is the byte offset into the function. + // 0 means no instructions have executed yet. -1 means the offset is unknown. + // On architectures where the pc points to the next instruction that will execute, this + // offset value will have already been decremented by 1 to stay within the bounds of the + // correct function body. + lldb::UnwindPlanSP + GetUnwindPlanAtCallSite (int current_offset); + + lldb::UnwindPlanSP + GetUnwindPlanAtNonCallSite (lldb_private::Thread& thread); + + lldb::UnwindPlanSP + GetUnwindPlanFastUnwind (lldb_private::Thread& Thread); + + lldb::UnwindPlanSP + GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread); + + lldb::UnwindPlanSP + GetUnwindPlanArchitectureDefaultAtFunctionEntry (lldb_private::Thread& thread); + + Address& + GetFirstNonPrologueInsn (Target& target); + + const Address& + GetFunctionStartAddress () const; + + bool + ContainsAddress (const Address& addr) const + { + return m_range.ContainsFileAddress (addr); + } + + // When we're doing an unwind using the UnwindPlanAtNonCallSite and we find an + // impossible unwind condition, we know that the UnwindPlan is invalid. Calling + // this method on the FuncUnwinder will tell it to replace that UnwindPlan with + // the architectural default UnwindPlan so hopefully our stack walk will get past + // this frame. + void + InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& Thread); + +private: + UnwindTable& m_unwind_table; + UnwindAssembly *m_assembly_profiler; + AddressRange m_range; + + Mutex m_mutex; + lldb::UnwindPlanSP m_unwind_plan_call_site_sp; + lldb::UnwindPlanSP m_unwind_plan_non_call_site_sp; + lldb::UnwindPlanSP m_unwind_plan_fast_sp; + lldb::UnwindPlanSP m_unwind_plan_arch_default_sp; + lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp; + + bool m_tried_unwind_at_call_site:1, + m_tried_unwind_at_non_call_site:1, + m_tried_unwind_fast:1, + m_tried_unwind_arch_default:1, + m_tried_unwind_arch_default_at_func_entry:1; + + + Address m_first_non_prologue_insn; + + DISALLOW_COPY_AND_ASSIGN (FuncUnwinders); + +}; // class FuncUnwinders + +} // namespace lldb_private + + +#endif //liblldb_FuncUnwinders_h diff --git a/include/lldb/Symbol/Function.h b/include/lldb/Symbol/Function.h new file mode 100644 index 0000000..787f81c --- /dev/null +++ b/include/lldb/Symbol/Function.h @@ -0,0 +1,638 @@ +//===-- Function.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_Function_h_ +#define liblldb_Function_h_ + +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/Declaration.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Core/UserID.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class FunctionInfo Function.h "lldb/Symbol/Function.h" +/// @brief A class that contains generic function information. +/// +/// This provides generic function information that gets resused between +/// inline functions and function types. +//---------------------------------------------------------------------- +class FunctionInfo +{ +public: + //------------------------------------------------------------------ + /// Construct with the function method name and optional declaration + /// information. + /// + /// @param[in] name + /// A C string name for the method name for this function. This + /// value should not be the mangled named, but the simple method + /// name. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + //------------------------------------------------------------------ + FunctionInfo (const char *name, const Declaration *decl_ptr); + + //------------------------------------------------------------------ + /// Construct with the function method name and optional declaration + /// information. + /// + /// @param[in] name + /// A name for the method name for this function. This value + /// should not be the mangled named, but the simple method name. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + //------------------------------------------------------------------ + FunctionInfo (const ConstString& name, const Declaration *decl_ptr); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since classes inherit from this class. + //------------------------------------------------------------------ + virtual + ~FunctionInfo (); + + //------------------------------------------------------------------ + /// Compare two function information objects. + /// + /// First compares the method names, and if equal, then compares + /// the declaration information. + /// + /// @param[in] lhs + /// The Left Hand Side const FunctionInfo object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const FunctionInfo object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + Compare (const FunctionInfo& lhs, const FunctionInfo& rhs); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s, bool show_fullpaths) const; + + //------------------------------------------------------------------ + /// Get accessor for the declaration information. + /// + /// @return + /// A reference to the declaration object. + //------------------------------------------------------------------ + Declaration& + GetDeclaration (); + + //------------------------------------------------------------------ + /// Get const accessor for the declaration information. + /// + /// @return + /// A const reference to the declaration object. + //------------------------------------------------------------------ + const Declaration& + GetDeclaration () const; + + //------------------------------------------------------------------ + /// Get accessor for the method name. + /// + /// @return + /// A const reference to the method name object. + //------------------------------------------------------------------ + const ConstString& + GetName () const; + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + virtual size_t + MemorySize () const; + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + ConstString m_name; ///< Function method name (not a mangled name). + Declaration m_declaration; ///< Information describing where this function information was defined. +}; + + +//---------------------------------------------------------------------- +/// @class InlineFunctionInfo Function.h "lldb/Symbol/Function.h" +/// @brief A class that describes information for an inlined function. +//---------------------------------------------------------------------- +class InlineFunctionInfo : public FunctionInfo +{ +public: + //------------------------------------------------------------------ + /// Construct with the function method name, mangled name, and + /// optional declaration information. + /// + /// @param[in] name + /// A C string name for the method name for this function. This + /// value should not be the mangled named, but the simple method + /// name. + /// + /// @param[in] mangled + /// A C string name for the mangled name for this function. This + /// value can be NULL if there is no mangled information. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + /// + /// @param[in] call_decl_ptr + /// Optional calling location declaration information that + /// describes from where this inlined function was called. + //------------------------------------------------------------------ + InlineFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr); + + //------------------------------------------------------------------ + /// Construct with the function method name, mangled name, and + /// optional declaration information. + /// + /// @param[in] name + /// A name for the method name for this function. This value + /// should not be the mangled named, but the simple method name. + /// + /// @param[in] mangled + /// A name for the mangled name for this function. This value + /// can be empty if there is no mangled information. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + /// + /// @param[in] call_decl_ptr + /// Optional calling location declaration information that + /// describes from where this inlined function was called. + //------------------------------------------------------------------ + InlineFunctionInfo(const ConstString& name, const Mangled &mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~InlineFunctionInfo(); + + //------------------------------------------------------------------ + /// Compare two inlined function information objects. + /// + /// First compares the FunctionInfo objects, and if equal, + /// compares the mangled names. + /// + /// @param[in] lhs + /// The Left Hand Side const InlineFunctionInfo object + /// reference. + /// + /// @param[in] rhs + /// The Right Hand Side const InlineFunctionInfo object + /// reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + int + Compare(const InlineFunctionInfo& lhs, const InlineFunctionInfo& rhs); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump(Stream *s, bool show_fullpaths) const; + + void + DumpStopContext (Stream *s) const; + + const ConstString & + GetName () const; + + //------------------------------------------------------------------ + /// Get accessor for the call site declaration information. + /// + /// @return + /// A reference to the declaration object. + //------------------------------------------------------------------ + Declaration& + GetCallSite (); + + //------------------------------------------------------------------ + /// Get const accessor for the call site declaration information. + /// + /// @return + /// A const reference to the declaration object. + //------------------------------------------------------------------ + const Declaration& + GetCallSite () const; + + //------------------------------------------------------------------ + /// Get accessor for the mangled name object. + /// + /// @return + /// A reference to the mangled name object. + //------------------------------------------------------------------ + Mangled& + GetMangled(); + + //------------------------------------------------------------------ + /// Get const accessor for the mangled name object. + /// + /// @return + /// A const reference to the mangled name object. + //------------------------------------------------------------------ + const Mangled& + GetMangled() const; + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + virtual size_t + MemorySize() const; + +private: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + Mangled m_mangled; ///< Mangled inlined function name (can be empty if there is no mangled information). + Declaration m_call_decl; +}; + +//---------------------------------------------------------------------- +/// @class Function Function.h "lldb/Symbol/Function.h" +/// @brief A class that describes a function. +/// +/// Functions belong to CompileUnit objects (Function::m_comp_unit), +/// have unique user IDs (Function::UserID), know how to reconstruct +/// their symbol context (Function::SymbolContextScope), have a +/// specific function type (Function::m_type_uid), have a simple +/// method name (FunctionInfo::m_name), be declared at a specific +/// location (FunctionInfo::m_declaration), possibly have mangled +/// names (Function::m_mangled), an optional return type +/// (Function::m_type), and contains lexical blocks +/// (Function::m_blocks). +/// +/// The function inforation is split into a few pieces: +/// @li The concrete instance information +/// @li The abstract information +/// +/// The abstract information is found in the function type (Type) that +/// describes a function information, return type and parameter types. +/// +/// The concreate information is the address range information and +/// specific locations for an instance of this function. +//---------------------------------------------------------------------- +class Function : + public UserID, + public SymbolContextScope +{ +public: + //------------------------------------------------------------------ + /// Construct with a compile unit, function UID, function type UID, + /// optional mangled name, function type, and a section offset + /// based address range. + /// + /// @param[in] comp_unit + /// The compile unit to which this function belongs. + /// + /// @param[in] func_uid + /// The UID for this function. This value is provided by the + /// SymbolFile plug-in and can be any value that allows + /// the plug-in to quickly find and parse more detailed + /// information when and if more information is needed. + /// + /// @param[in] func_type_uid + /// The type UID for the function Type to allow for lazy type + /// parsing from the debug information. + /// + /// @param[in] mangled + /// The optional mangled name for this function. If empty, there + /// is no mangled information. + /// + /// @param[in] func_type + /// The optional function type. If NULL, the function type will + /// be parsed on demand when accessed using the + /// Function::GetType() function by asking the SymbolFile + /// plug-in to get the type for \a func_type_uid. + /// + /// @param[in] range + /// The section offset based address for this function. + //------------------------------------------------------------------ + Function ( + CompileUnit *comp_unit, + lldb::user_id_t func_uid, + lldb::user_id_t func_type_uid, + const Mangled &mangled, + Type * func_type, + const AddressRange& range); + + //------------------------------------------------------------------ + /// Construct with a compile unit, function UID, function type UID, + /// optional mangled name, function type, and a section offset + /// based address range. + /// + /// @param[in] comp_unit + /// The compile unit to which this function belongs. + /// + /// @param[in] func_uid + /// The UID for this function. This value is provided by the + /// SymbolFile plug-in and can be any value that allows + /// the plug-in to quickly find and parse more detailed + /// information when and if more information is needed. + /// + /// @param[in] func_type_uid + /// The type UID for the function Type to allow for lazy type + /// parsing from the debug information. + /// + /// @param[in] mangled + /// The optional mangled name for this function. If empty, there + /// is no mangled information. + /// + /// @param[in] func_type + /// The optional function type. If NULL, the function type will + /// be parsed on demand when accessed using the + /// Function::GetType() function by asking the SymbolFile + /// plug-in to get the type for \a func_type_uid. + /// + /// @param[in] range + /// The section offset based address for this function. + //------------------------------------------------------------------ + Function ( + CompileUnit *comp_unit, + lldb::user_id_t func_uid, + lldb::user_id_t func_type_uid, + const char *mangled, + Type * func_type, + const AddressRange& range); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~Function (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext(SymbolContext* sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual CompileUnit * + CalculateSymbolContextCompileUnit (); + + virtual Function * + CalculateSymbolContextFunction (); + + const AddressRange & + GetAddressRange() + { + return m_range; + } + + //------------------------------------------------------------------ + /// Find the file and line number of the source location of the start + /// of the function. This will use the declaration if present and fall + /// back on the line table if that fails. So there may NOT be a line + /// table entry for this source file/line combo. + /// + /// @param[out] source_file + /// The source file. + /// + /// @param[out] line_no + /// The line number. + //------------------------------------------------------------------ + void + GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no); + + //------------------------------------------------------------------ + /// Find the file and line number of the source location of the end + /// of the function. + /// + /// + /// @param[out] source_file + /// The source file. + /// + /// @param[out] line_no + /// The line number. + //------------------------------------------------------------------ + void + GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no); + + //------------------------------------------------------------------ + /// Get accessor for the block list. + /// + /// @return + /// The block list object that describes all lexical blocks + /// in the function. + /// + /// @see BlockList + //------------------------------------------------------------------ + Block& + GetBlock (bool can_create); + + //------------------------------------------------------------------ + /// Get accessor for the compile unit that owns this function. + /// + /// @return + /// A compile unit object pointer. + //------------------------------------------------------------------ + CompileUnit* + GetCompileUnit(); + + //------------------------------------------------------------------ + /// Get const accessor for the compile unit that owns this function. + /// + /// @return + /// A const compile unit object pointer. + //------------------------------------------------------------------ + const CompileUnit* + GetCompileUnit() const; + + void + GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target); + + //------------------------------------------------------------------ + /// Get accessor for the frame base location. + /// + /// @return + /// A location expression that describes the function frame + /// base. + //------------------------------------------------------------------ + DWARFExpression & + GetFrameBaseExpression() + { + return m_frame_base; + } + + //------------------------------------------------------------------ + /// Get const accessor for the frame base location. + /// + /// @return + /// A const compile unit object pointer. + //------------------------------------------------------------------ + const DWARFExpression & + GetFrameBaseExpression() const + { + return m_frame_base; + } + + const ConstString & + GetName() const + { + return m_mangled.GetName(); + } + + const Mangled & + GetMangled() const + { + return m_mangled; + } + + //------------------------------------------------------------------ + /// Get the DeclContext for this function, if available. + /// + /// @return + /// The DeclContext, or NULL if none exists. + //------------------------------------------------------------------ + clang::DeclContext * + GetClangDeclContext(); + + //------------------------------------------------------------------ + /// Get accessor for the type that describes the function + /// return value type, and paramter types. + /// + /// @return + /// A type object pointer. + //------------------------------------------------------------------ + Type* + GetType(); + + //------------------------------------------------------------------ + /// Get const accessor for the type that describes the function + /// return value type, and paramter types. + /// + /// @return + /// A const type object pointer. + //------------------------------------------------------------------ + const Type* + GetType() const; + + ClangASTType + GetClangType (); + + uint32_t + GetPrologueByteSize (); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] show_context + /// If \b true, variables will dump their symbol context + /// information. + //------------------------------------------------------------------ + void + Dump(Stream *s, bool show_context) const; + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext(Stream *s); + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + size_t + MemorySize () const; + +protected: + + enum + { + flagsCalculatedPrologueSize = (1 << 0) ///< Have we already tried to calculate the prologue size? + }; + + + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + CompileUnit *m_comp_unit; ///< The compile unit that owns this function. + lldb::user_id_t m_type_uid; ///< The user ID of for the prototype Type for this function. + Type * m_type; ///< The function prototype type for this function that include the function info (FunctionInfo), return type and parameters. + Mangled m_mangled; ///< The mangled function name if any, if empty, there is no mangled information. + Block m_block; ///< All lexical blocks contained in this function. + AddressRange m_range; ///< The function address range that covers the widest range needed to contain all blocks + DWARFExpression m_frame_base; ///< The frame base expression for variables that are relative to the frame pointer. + Flags m_flags; + uint32_t m_prologue_byte_size; ///< Compute the prologue size once and cache it +private: + DISALLOW_COPY_AND_ASSIGN(Function); +}; + +} // namespace lldb_private + +#endif // liblldb_Function_h_ diff --git a/include/lldb/Symbol/LineEntry.h b/include/lldb/Symbol/LineEntry.h new file mode 100644 index 0000000..d7750cd --- /dev/null +++ b/include/lldb/Symbol/LineEntry.h @@ -0,0 +1,174 @@ +//===-- LineEntry.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_LineEntry_h_ +#define liblldb_LineEntry_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Host/FileSpec.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class LineEntry LineEntry.h "lldb/Symbol/LineEntry.h" +/// @brief A line table entry class. +//---------------------------------------------------------------------- +struct LineEntry +{ + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize all member variables to invalid values. + //------------------------------------------------------------------ + LineEntry (); + + LineEntry + ( + const lldb::SectionSP §ion_sp, + lldb::addr_t section_offset, + lldb::addr_t byte_size, + const FileSpec &file, + uint32_t _line, + uint16_t _column, + bool _is_start_of_statement, + bool _is_start_of_basic_block, + bool _is_prologue_end, + bool _is_epilogue_begin, + bool _is_terminal_entry + ); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Clears all member variables to invalid values. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] comp_unit + /// The compile unit object that contains the support file + /// list so the line entry can dump the file name (since this + /// object contains a file index into the support file list). + /// + /// @param[in] show_file + /// If \b true, display the filename with the line entry which + /// requires that the compile unit object \a comp_unit be a + /// valid pointer. + /// + /// @param[in] style + /// The display style for the section offset address. + /// + /// @return + /// Returns \b true if the address was able to be displayed + /// using \a style. File and load addresses may be unresolved + /// and it may not be possible to display a valid address value. + /// Returns \b false if the address was not able to be properly + /// dumped. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ + bool + Dump (Stream *s, Target *target, bool show_file, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_range) const; + + bool + GetDescription (Stream *s, + lldb::DescriptionLevel level, + CompileUnit* cu, + Target *target, + bool show_address_only) const; + + //------------------------------------------------------------------ + /// Dumps information specific to a process that stops at this + /// line entry to the supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] comp_unit + /// The compile unit object that contains the support file + /// list so the line entry can dump the file name (since this + /// object contains a file index into the support file list). + /// + /// @return + /// Returns \b true if the file and line were properly dumped, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + DumpStopContext (Stream *s, bool show_fullpaths) const; + + //------------------------------------------------------------------ + /// Check if a line entry object is valid. + /// + /// @return + /// Returns \b true if the line entry contains a valid section + /// offset address, file index, and line number, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + IsValid () const; + + //------------------------------------------------------------------ + /// Compare two LineEntry objects. + /// + /// @param[in] lhs + /// The Left Hand Side const LineEntry object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const LineEntry object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + Compare (const LineEntry& lhs, const LineEntry& rhs); + + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + AddressRange range; ///< The section offset address range for this line entry. + FileSpec file; + uint32_t line; ///< The source line number, or zero if there is no line number information. + uint16_t column; ///< The column number of the source line, or zero if there is no column information. + uint16_t is_start_of_statement:1, ///< Indicates this entry is the beginning of a statement. + is_start_of_basic_block:1, ///< Indicates this entry is the beginning of a basic block. + is_prologue_end:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an entry breakpoint of a function. + is_epilogue_begin:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an exit breakpoint of a function. + is_terminal_entry:1; ///< Indicates this entry is that of the first byte after the end of a sequence of target machine instructions. +}; + +//------------------------------------------------------------------ +/// Less than operator. +/// +/// @param[in] lhs +/// The Left Hand Side const LineEntry object reference. +/// +/// @param[in] rhs +/// The Right Hand Side const LineEntry object reference. +/// +/// @return +/// Returns \b true if lhs < rhs, false otherwise. +//------------------------------------------------------------------ +bool operator<(const LineEntry& lhs, const LineEntry& rhs); + +} // namespace lldb_private + +#endif // liblldb_LineEntry_h_ diff --git a/include/lldb/Symbol/LineTable.h b/include/lldb/Symbol/LineTable.h new file mode 100644 index 0000000..477c845 --- /dev/null +++ b/include/lldb/Symbol/LineTable.h @@ -0,0 +1,422 @@ +//===-- LineTable.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_LineTable_h_ +#define liblldb_LineTable_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/LineEntry.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/RangeMap.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class LineSequence LineTable.h "lldb/Symbol/LineTable.h" +/// @brief An abstract base class used during symbol table creation. +//---------------------------------------------------------------------- +class LineSequence +{ +public: + LineSequence (); + + virtual + ~LineSequence() {} + + virtual void + Clear() = 0; + +private: + DISALLOW_COPY_AND_ASSIGN (LineSequence); +}; + +//---------------------------------------------------------------------- +/// @class LineTable LineTable.h "lldb/Symbol/LineTable.h" +/// @brief A line table class. +//---------------------------------------------------------------------- +class LineTable +{ +public: + //------------------------------------------------------------------ + /// Construct with compile unit. + /// + /// @param[in] comp_unit + /// The compile unit to which this line table belongs. + //------------------------------------------------------------------ + LineTable (CompileUnit* comp_unit); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~LineTable (); + + //------------------------------------------------------------------ + /// Adds a new line entry to this line table. + /// + /// All line entries are maintained in file address order. + /// + /// @param[in] line_entry + /// A const reference to a new line_entry to add to this line + /// table. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ +// void +// AddLineEntry (const LineEntry& line_entry); + + // Called when you can't guarantee the addresses are in increasing order + void + InsertLineEntry (lldb::addr_t file_addr, + uint32_t line, + uint16_t column, + uint16_t file_idx, + bool is_start_of_statement, + bool is_start_of_basic_block, + bool is_prologue_end, + bool is_epilogue_begin, + bool is_terminal_entry); + + // Used to instantiate the LineSequence helper classw + LineSequence* + CreateLineSequenceContainer (); + + // Append an entry to a caller-provided collection that will later be + // inserted in this line table. + void + AppendLineEntryToSequence (LineSequence* sequence, + lldb::addr_t file_addr, + uint32_t line, + uint16_t column, + uint16_t file_idx, + bool is_start_of_statement, + bool is_start_of_basic_block, + bool is_prologue_end, + bool is_epilogue_begin, + bool is_terminal_entry); + + // Insert a sequence of entries into this line table. + void + InsertSequence (LineSequence* sequence); + + //------------------------------------------------------------------ + /// Dump all line entries in this line table to the stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] style + /// The display style for the address. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ + void + Dump (Stream *s, Target *target, + Address::DumpStyle style, + Address::DumpStyle fallback_style, + bool show_line_ranges); + + void + GetDescription (Stream *s, + Target *target, + lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Find a line entry that contains the section offset address \a + /// so_addr. + /// + /// @param[in] so_addr + /// A section offset address object containing the address we + /// are searching for. + /// + /// @param[out] line_entry + /// A copy of the line entry that was found if \b true is + /// returned, otherwise \a entry is left unmodified. + /// + /// @param[out] index_ptr + /// A pointer to a 32 bit integer that will get the actual line + /// entry index if it is not NULL. + /// + /// @return + /// Returns \b true if \a so_addr is contained in a line entry + /// in this line table, \b false otherwise. + //------------------------------------------------------------------ + bool + FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr = NULL); + + //------------------------------------------------------------------ + /// Find a line entry index that has a matching file index and + /// source line number. + /// + /// Finds the next line entry that has a matching \a file_idx and + /// source line number \a line starting at the \a start_idx entries + /// into the line entry collection. + /// + /// @param[in] start_idx + /// The number of entries to skip when starting the search. + /// + /// @param[out] file_idx + /// The file index to search for that should be found prior + /// to calling this function using the following functions: + /// CompileUnit::GetSupportFiles() + /// FileSpecList::FindFileIndex (uint32_t, const FileSpec &) const + /// + /// @param[in] line + /// The source line to match. + /// + /// @param[in] exact + /// If true, match only if you find a line entry exactly matching \a line. + /// If false, return the closest line entry greater than \a line. + /// + /// @param[out] line_entry + /// A reference to a line entry object that will get a copy of + /// the line entry if \b true is returned, otherwise \a + /// line_entry is left untouched. + /// + /// @return + /// Returns \b true if a matching line entry is found in this + /// line table, \b false otherwise. + /// + /// @see CompileUnit::GetSupportFiles() + /// @see FileSpecList::FindFileIndex (uint32_t, const FileSpec &) const + //------------------------------------------------------------------ + uint32_t + FindLineEntryIndexByFileIndex (uint32_t start_idx, + uint32_t file_idx, + uint32_t line, + bool exact, + LineEntry* line_entry_ptr); + + uint32_t + FindLineEntryIndexByFileIndex (uint32_t start_idx, + const std::vector<uint32_t> &file_indexes, + uint32_t line, + bool exact, + LineEntry* line_entry_ptr); + + size_t + FineLineEntriesForFileIndex (uint32_t file_idx, + bool append, + SymbolContextList &sc_list); + + //------------------------------------------------------------------ + /// Get the line entry from the line table at index \a idx. + /// + /// @param[in] idx + /// An index into the line table entry collection. + /// + /// @return + /// A valid line entry if \a idx is a valid index, or an invalid + /// line entry if \a idx is not valid. + /// + /// @see LineTable::GetSize() + /// @see LineEntry::IsValid() const + //------------------------------------------------------------------ + bool + GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry); + + //------------------------------------------------------------------ + /// Gets the size of the line table in number of line table entries. + /// + /// @return + /// The number of line table entries in this line table. + //------------------------------------------------------------------ + uint32_t + GetSize () const; + + typedef lldb_private::RangeArray<lldb::addr_t, lldb::addr_t, 32> FileAddressRanges; + + //------------------------------------------------------------------ + /// Gets all contiguous file address ranges for the entire line table. + /// + /// @param[out] file_ranges + /// A collection of file address ranges that will be filled in + /// by this function. + /// + /// @param[out] append + /// If \b true, then append to \a file_ranges, otherwise clear + /// \a file_ranges prior to adding any ranges. + /// + /// @return + /// The number of address ranges added to \a file_ranges + //------------------------------------------------------------------ + size_t + GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append); + + //------------------------------------------------------------------ + /// Given a file range link map, relink the current line table + /// and return a fixed up line table. + /// + /// @param[out] file_range_map + /// A collection of file ranges that maps to new file ranges + /// that will be used when linking the line table. + /// + /// @return + /// A new line table if at least one line table entry was able + /// to be mapped. + //------------------------------------------------------------------ + typedef RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t> FileRangeMap; + + LineTable * + LinkLineTable (const FileRangeMap &file_range_map); + +protected: + + struct Entry + { + Entry () : + file_addr (LLDB_INVALID_ADDRESS), + line (0), + column (0), + file_idx (0), + is_start_of_statement (false), + is_start_of_basic_block (false), + is_prologue_end (false), + is_epilogue_begin (false), + is_terminal_entry (false) + { + } + + Entry ( lldb::addr_t _file_addr, + uint32_t _line, + uint16_t _column, + uint16_t _file_idx, + bool _is_start_of_statement, + bool _is_start_of_basic_block, + bool _is_prologue_end, + bool _is_epilogue_begin, + bool _is_terminal_entry) : + file_addr (_file_addr), + line (_line), + column (_column), + file_idx (_file_idx), + is_start_of_statement (_is_start_of_statement), + is_start_of_basic_block (_is_start_of_basic_block), + is_prologue_end (_is_prologue_end), + is_epilogue_begin (_is_epilogue_begin), + is_terminal_entry (_is_terminal_entry) + { + } + + int + bsearch_compare (const void *key, const void *arrmem); + + void + Clear () + { + file_addr = LLDB_INVALID_ADDRESS; + line = 0; + column = 0; + file_idx = 0; + is_start_of_statement = false; + is_start_of_basic_block = false; + is_prologue_end = false; + is_epilogue_begin = false; + is_terminal_entry = false; + } + + static int + Compare (const Entry& lhs, const Entry& rhs) + { + // Compare the sections before calling + #define SCALAR_COMPARE(a,b) if (a < b) return -1; if (a > b) return +1 + SCALAR_COMPARE (lhs.file_addr, rhs.file_addr); + SCALAR_COMPARE (lhs.line, rhs.line); + SCALAR_COMPARE (lhs.column, rhs.column); + SCALAR_COMPARE (lhs.is_start_of_statement, rhs.is_start_of_statement); + SCALAR_COMPARE (lhs.is_start_of_basic_block, rhs.is_start_of_basic_block); + // rhs and lhs reversed on purpose below. + SCALAR_COMPARE (rhs.is_prologue_end, lhs.is_prologue_end); + SCALAR_COMPARE (lhs.is_epilogue_begin, rhs.is_epilogue_begin); + // rhs and lhs reversed on purpose below. + SCALAR_COMPARE (rhs.is_terminal_entry, lhs.is_terminal_entry); + SCALAR_COMPARE (lhs.file_idx, rhs.file_idx); + #undef SCALAR_COMPARE + return 0; + } + + + class LessThanBinaryPredicate + { + public: + LessThanBinaryPredicate(LineTable *line_table); + bool operator() (const LineTable::Entry&, const LineTable::Entry&) const; + protected: + LineTable *m_line_table; + }; + + static bool EntryAddressLessThan (const Entry& lhs, const Entry& rhs) + { + return lhs.file_addr < rhs.file_addr; + } + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + lldb::addr_t file_addr; ///< The file address for this line entry + uint32_t line; ///< The source line number, or zero if there is no line number information. + uint16_t column; ///< The column number of the source line, or zero if there is no column information. + uint16_t file_idx:11, ///< The file index into CompileUnit's file table, or zero if there is no file information. + is_start_of_statement:1, ///< Indicates this entry is the beginning of a statement. + is_start_of_basic_block:1, ///< Indicates this entry is the beginning of a basic block. + is_prologue_end:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an entry breakpoint of a function. + is_epilogue_begin:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an exit breakpoint of a function. + is_terminal_entry:1; ///< Indicates this entry is that of the first byte after the end of a sequence of target machine instructions. + }; + + struct EntrySearchInfo + { + LineTable* line_table; + lldb_private::Section *a_section; + Entry *a_entry; + }; + + //------------------------------------------------------------------ + // Types + //------------------------------------------------------------------ + typedef std::vector<lldb_private::Section*> section_collection; ///< The collection type for the sections. + typedef std::vector<Entry> entry_collection; ///< The collection type for the line entries. + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + CompileUnit* m_comp_unit; ///< The compile unit that this line table belongs to. + entry_collection m_entries; ///< The collection of line entries in this line table. + + //------------------------------------------------------------------ + // Helper class + //------------------------------------------------------------------ + class LineSequenceImpl : public LineSequence + { + public: + LineSequenceImpl() : + LineSequence() + {} + + virtual + ~LineSequenceImpl() + {} + + virtual void + Clear(); + + entry_collection m_entries; ///< The collection of line entries in this sequence. + }; + + bool + ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry); + +private: + DISALLOW_COPY_AND_ASSIGN (LineTable); +}; + +} // namespace lldb_private + +#endif // liblldb_LineTable_h_ diff --git a/include/lldb/Symbol/ObjectContainer.h b/include/lldb/Symbol/ObjectContainer.h new file mode 100644 index 0000000..7fb6862 --- /dev/null +++ b/include/lldb/Symbol/ObjectContainer.h @@ -0,0 +1,236 @@ +//===-- ObjectContainer.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_ObjectContainer_h_ +#define liblldb_ObjectContainer_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Host/Endian.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ObjectContainer ObjectContainer.h "lldb/Symbol/ObjectContainer.h" +/// @brief A plug-in interface definition class for object containers. +/// +/// Object containers contain object files from one or more +/// architectures, and also can contain one or more named objects. +/// +/// Typical object containers are static libraries (.a files) that +/// contain multiple named object files, and universal files that contain +/// multiple architectures. +//---------------------------------------------------------------------- +class ObjectContainer : + public PluginInterface, + public ModuleChild +{ +public: + //------------------------------------------------------------------ + /// Construct with a parent module, offset, and header data. + /// + /// Object files belong to modules and a valid module must be + /// supplied upon construction. The at an offset within a file for + /// objects that contain more than one architecture or object. + //------------------------------------------------------------------ + ObjectContainer (const lldb::ModuleSP &module_sp, + const FileSpec *file, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset) : + ModuleChild (module_sp), + m_file (), // This file can be different than the module's file spec + m_offset (file_offset), + m_length (length), + m_data () + { + if (file) + m_file = *file; + if (data_sp) + m_data.SetData (data_sp, data_offset, length); + } + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~ObjectContainer() + { + } + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the current contents of this object + /// to the supplied stream \a s. The dumping should include the + /// section list if it has been parsed, and the symbol table + /// if it has been parsed. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + virtual void + Dump (Stream *s) const = 0; + + //------------------------------------------------------------------ + /// Gets the architecture given an index. + /// + /// Copies the architecture specification for index \a idx. + /// + /// @param[in] idx + /// The architecture index to extract. + /// + /// @param[out] arch + /// A architecture object that will be filled in if \a idx is a + /// architecture valid index. + /// + /// @return + /// Returns \b true if \a idx is valid and \a arch has been + /// filled in, \b false otherwise. + /// + /// @see ObjectContainer::GetNumArchitectures() const + //------------------------------------------------------------------ + virtual bool + GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const + { + return false; + } + + //------------------------------------------------------------------ + /// Returns the offset into a file at which this object resides. + /// + /// Some files contain many object files, and this function allows + /// access to an object's offset within the file. + /// + /// @return + /// The offset in bytes into the file. Defaults to zero for + /// simple object files that a represented by an entire file. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetOffset () const + { return m_offset; } + + virtual lldb::addr_t + GetByteSize () const + { return m_length; } + + //------------------------------------------------------------------ + /// Get the number of objects within this object file (archives). + /// + /// @return + /// Zero for object files that are not archives, or the number + /// of objects contained in the archive. + //------------------------------------------------------------------ + virtual size_t + GetNumObjects () const + { return 0; } + + //------------------------------------------------------------------ + /// Get the number of architectures in this object file. + /// + /// The default implementation returns 1 as for object files that + /// contain a single architecture. ObjectContainer instances that + /// contain more than one architecture should override this function + /// and return an appropriate value. + /// + /// @return + /// The number of architectures contained in this object file. + //------------------------------------------------------------------ + virtual size_t + GetNumArchitectures () const + { return 0; } + + //------------------------------------------------------------------ + /// Attempts to parse the object header. + /// + /// This function is used as a test to see if a given plug-in + /// instance can parse the header data already contained in + /// ObjectContainer::m_data. If an object file parser does not + /// recognize that magic bytes in a header, false should be returned + /// and the next plug-in can attempt to parse an object file. + /// + /// @return + /// Returns \b true if the header was parsed succesfully, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + ParseHeader () = 0; + + //------------------------------------------------------------------ + /// Selects an architecture in an object file. + /// + /// Object files that contain a single architecture should verify + /// that the specified \a arch matches the architecture in in + /// object file and return \b true or \b false accordingly. + /// + /// Object files that contain more than one architecture should + /// attempt to select that architecture, and if successful, clear + /// out any previous state from any previously selected architecture + /// and prepare to return information for the new architecture. + /// + /// @return + /// Returns a pointer to the object file of the requested \a + /// arch and optional \a name. Returns NULL of no such object + /// file exists in the container. + //------------------------------------------------------------------ + virtual lldb::ObjectFileSP + GetObjectFile (const FileSpec *file) = 0; + + virtual bool + ObjectAtIndexIsContainer (uint32_t object_idx) + { + return false; + } + + virtual ObjectFile * + GetObjectFileAtIndex (uint32_t object_idx) + { + return NULL; + } + + virtual ObjectContainer * + GetObjectContainerAtIndex (uint32_t object_idx) + { + return NULL; + } + + virtual const char * + GetObjectNameAtIndex (uint32_t object_idx) const + { + return NULL; + } + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + FileSpec m_file; ///< The file that represents this container objects (which can be different from the module's file). + lldb::addr_t m_offset; ///< The offset in bytes into the file, or the address in memory + lldb::addr_t m_length; ///< The size in bytes if known (can be zero). + DataExtractor m_data; ///< The data for this object file so things can be parsed lazily. + +private: + DISALLOW_COPY_AND_ASSIGN (ObjectContainer); +}; + +} // namespace lldb_private + +#endif // liblldb_ObjectContainer_h_ diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h new file mode 100644 index 0000000..8934c31 --- /dev/null +++ b/include/lldb/Symbol/ObjectFile.h @@ -0,0 +1,706 @@ +//===-- ObjectFile.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_ObjectFile_h_ +#define liblldb_ObjectFile_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/Symtab.h" +#include "lldb/Symbol/UnwindTable.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ObjectFile ObjectFile.h "lldb/Symbol/ObjectFile.h" +/// @brief A plug-in interface definition class for object file parsers. +/// +/// Object files belong to Module objects and know how to extract +/// information from executable, shared library, and object (.o) files +/// used by operating system runtime. The symbol table and section list +/// for an object file. +/// +/// Object files can be represented by the entire file, or by part of a +/// file. Examples of object files that are part of a file include +/// object files that contain information for multiple architectures in +/// the same file, or archive files that contain multiple objects +/// (ranlib archives) (possibly for multiple architectures as well). +/// +/// Object archive files (e.g. ranlib archives) can contain +/// multiple .o (object) files that must be selected by index or by name. +/// The number of objects that an ObjectFile contains can be determined +/// using the ObjectFile::GetNumObjects() const +/// function, and followed by a call to +/// ObjectFile::SelectObjectAtIndex (uint32_t) to change the currently +/// selected object. Objects can also be selected by name using the +/// ObjectFile::SelectObject(const char *) function. +/// +/// Once an architecture is selected (and an object is selected for +/// for archives), the object file information can be extracted from +/// this abstract class. +//---------------------------------------------------------------------- +class ObjectFile: + public std::enable_shared_from_this<ObjectFile>, + public PluginInterface, + public ModuleChild +{ +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, + eStrataRawImage + } Strata; + + //------------------------------------------------------------------ + /// Construct with a parent module, offset, and header data. + /// + /// Object files belong to modules and a valid module must be + /// supplied upon construction. The at an offset within a file for + /// objects that contain more than one architecture or object. + //------------------------------------------------------------------ + ObjectFile (const lldb::ModuleSP &module_sp, + const FileSpec *file_spec_ptr, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset); + + ObjectFile (const lldb::ModuleSP &module_sp, + const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, + lldb::DataBufferSP& data_sp); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~ObjectFile(); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the current contents of this object + /// to the supplied stream \a s. The dumping should include the + /// section list if it has been parsed, and the symbol table + /// if it has been parsed. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + virtual void + Dump (Stream *s) = 0; + + //------------------------------------------------------------------ + /// Find a ObjectFile plug-in that can parse \a file_spec. + /// + /// Scans all loaded plug-in interfaces that implement versions of + /// the ObjectFile plug-in interface and returns the first + /// instance that can parse the file. + /// + /// @param[in] module + /// The parent module that owns this object file. + /// + /// @param[in] file_spec + /// A file specification that indicates which file to use as the + /// object file. + /// + /// @param[in] file_offset + /// The offset into the file at which to start parsing the + /// object. This is for files that contain multiple + /// architectures or objects. + /// + /// @param[in] file_size + /// The size of the current object file if it can be determined + /// or if it is known. This can be zero. + /// + /// @see ObjectFile::ParseHeader() + //------------------------------------------------------------------ + static lldb::ObjectFileSP + FindPlugin (const lldb::ModuleSP &module_sp, + const FileSpec* file_spec, + lldb::offset_t file_offset, + lldb::offset_t file_size, + lldb::DataBufferSP &data_sp, + lldb::offset_t &data_offset); + + //------------------------------------------------------------------ + /// Find a ObjectFile plug-in that can parse a file in memory. + /// + /// Scans all loaded plug-in interfaces that implement versions of + /// the ObjectFile plug-in interface and returns the first + /// instance that can parse the file. + /// + /// @param[in] module + /// The parent module that owns this object file. + /// + /// @param[in] process_sp + /// A shared pointer to the process whose memory space contains + /// an object file. This will be stored as a std::weak_ptr. + /// + /// @param[in] header_addr + /// The address of the header for the object file in memory. + //------------------------------------------------------------------ + static lldb::ObjectFileSP + FindPlugin (const lldb::ModuleSP &module_sp, + const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, + lldb::DataBufferSP &file_data_sp); + + + static size_t + GetModuleSpecifications (const FileSpec &file, + lldb::offset_t file_offset, + lldb::offset_t file_size, + ModuleSpecList &specs); + + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t file_size, + lldb_private::ModuleSpecList &specs); + //------------------------------------------------------------------ + /// Split a path into a file path with object name. + /// + /// For paths like "/tmp/foo.a(bar.o)" we often need to split a path + /// up into the actual path name and into the object name so we can + /// make a valid object file from it. + /// + /// @param[in] path_with_object + /// A path that might contain an archive path with a .o file + /// specified in parens in the basename of the path. + /// + /// @param[out] archive_file + /// If \b true is returned, \a file_spec will be filled in with + /// the path to the archive. + /// + /// @param[out] archive_object + /// If \b true is returned, \a object will be filled in with + /// the name of the object inside the archive. + /// + /// @return + /// \b true if the path matches the pattern of archive + object + /// and \a archive_file and \a archive_object are modified, + /// \b false otherwise and \a archive_file and \a archive_object + /// are guaranteed to be remain unchanged. + //------------------------------------------------------------------ + static bool + SplitArchivePathWithObject (const char *path_with_object, + lldb_private::FileSpec &archive_file, + lldb_private::ConstString &archive_object, + bool must_exist); + + //------------------------------------------------------------------ + /// Gets the address size in bytes for the current object file. + /// + /// @return + /// The size of an address in bytes for the currently selected + /// architecture (and object for archives). Returns zero if no + /// architecture or object has been selected. + //------------------------------------------------------------------ + virtual uint32_t + GetAddressByteSize () const = 0; + + //------------------------------------------------------------------ + /// Get the address type given a file address in an object file. + /// + /// Many binary file formats know what kinds + /// This is primarily for ARM binaries, though it can be applied to + /// any executable file format that supports different opcode types + /// within the same binary. ARM binaries support having both ARM and + /// Thumb within the same executable container. We need to be able + /// to get + /// @return + /// The size of an address in bytes for the currently selected + /// architecture (and object for archives). Returns zero if no + /// architecture or object has been selected. + //------------------------------------------------------------------ + virtual lldb::AddressClass + GetAddressClass (lldb::addr_t file_addr); + + //------------------------------------------------------------------ + /// Extract the dependent modules from an object file. + /// + /// If an object file has information about which other images it + /// depends on (such as shared libraries), this function will + /// provide the list. Since many executables or shared libraries + /// may depend on the same files, + /// FileSpecList::AppendIfUnique(const FileSpec &) should be + /// used to make sure any files that are added are not already in + /// the list. + /// + /// @param[out] file_list + /// A list of file specification objects that gets dependent + /// files appended to. + /// + /// @return + /// The number of new files that were appended to \a file_list. + /// + /// @see FileSpecList::AppendIfUnique(const FileSpec &) + //------------------------------------------------------------------ + virtual uint32_t + GetDependentModules (FileSpecList& file_list) = 0; + + //------------------------------------------------------------------ + /// Tells whether this object file is capable of being the main executable + /// for a process. + /// + /// @return + /// \b true if it is, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + IsExecutable () const = 0; + + //------------------------------------------------------------------ + /// Returns the offset into a file at which this object resides. + /// + /// Some files contain many object files, and this function allows + /// access to an object's offset within the file. + /// + /// @return + /// The offset in bytes into the file. Defaults to zero for + /// simple object files that a represented by an entire file. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetFileOffset () const + { return m_file_offset; } + + virtual lldb::addr_t + GetByteSize () const + { return m_length; } + + //------------------------------------------------------------------ + /// Get accessor to the object file specification. + /// + /// @return + /// The file specification object pointer if there is one, or + /// NULL if this object is only from memory. + //------------------------------------------------------------------ + virtual FileSpec& + GetFileSpec() { return m_file; } + + //------------------------------------------------------------------ + /// Get const accessor to the object file specification. + /// + /// @return + /// The const file specification object pointer if there is one, + /// or NULL if this object is only from memory. + //------------------------------------------------------------------ + virtual const FileSpec& + GetFileSpec() const { return m_file; } + + //------------------------------------------------------------------ + /// Get the name of the cpu, vendor and OS for this object file. + /// + /// This value is a string that represents the target triple where + /// the cpu type, the vendor and the OS are encoded into a string. + /// + /// @param[out] target_triple + /// The string value of the target triple. + /// + /// @return + /// \b True if the target triple was able to be computed, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + GetArchitecture (ArchSpec &arch) = 0; + + //------------------------------------------------------------------ + /// Gets the section list for the currently selected architecture + /// (and object for archives). + /// + /// Section list parsing can be deferred by ObjectFile instances + /// until this accessor is called the first time. + /// + /// @return + /// The list of sections contained in this object file. + //------------------------------------------------------------------ + virtual SectionList * + GetSectionList (); + + virtual void + CreateSections (SectionList &unified_section_list) = 0; + + //------------------------------------------------------------------ + /// Gets the symbol table for the currently selected architecture + /// (and object for archives). + /// + /// Symbol table parsing can be deferred by ObjectFile instances + /// until this accessor is called the first time. + /// + /// @return + /// The symbol table for this object file. + //------------------------------------------------------------------ + virtual Symtab * + GetSymtab () = 0; + + //------------------------------------------------------------------ + /// Detect if this object file has been stripped of local symbols. + /// + /// @return + /// Return \b true if the object file has been stripped of local + /// symbols. + //------------------------------------------------------------------ + virtual bool + IsStripped () = 0; + + //------------------------------------------------------------------ + /// Frees the symbol table. + /// + /// This function should only be used when an object file is + /// + /// @param[in] flags + /// eSymtabFromUnifiedSectionList: Whether to clear symbol table + /// for unified module section list, or object file. + /// + /// @return + /// The symbol table for this object file. + //------------------------------------------------------------------ + virtual void + ClearSymtab (); + + //------------------------------------------------------------------ + /// Gets the UUID for this object file. + /// + /// If the object file format contains a UUID, the value should be + /// returned. Else ObjectFile instances should return the MD5 + /// checksum of all of the bytes for the object file (or memory for + /// memory based object files). + /// + /// @return + /// Returns \b true if a UUID was successfully extracted into + /// \a uuid, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + GetUUID (lldb_private::UUID* uuid) = 0; + + //------------------------------------------------------------------ + /// Gets the symbol file spec list for this object file. + /// + /// If the object file format contains a debug symbol file link, + /// the values will be return in the FileSpecList. + /// + /// @return + /// Returns filespeclist. + //------------------------------------------------------------------ + virtual lldb_private::FileSpecList + GetDebugSymbolFilePaths() + { + return FileSpecList(); + } + + //------------------------------------------------------------------ + /// Gets whether endian swapping should occur when extracting data + /// from this object file. + /// + /// @return + /// Returns \b true if endian swapping is needed, \b false + /// otherwise. + //------------------------------------------------------------------ + virtual lldb::ByteOrder + GetByteOrder () const = 0; + + //------------------------------------------------------------------ + /// Attempts to parse the object header. + /// + /// This function is used as a test to see if a given plug-in + /// instance can parse the header data already contained in + /// ObjectFile::m_data. If an object file parser does not + /// recognize that magic bytes in a header, false should be returned + /// and the next plug-in can attempt to parse an object file. + /// + /// @return + /// Returns \b true if the header was parsed succesfully, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + ParseHeader () = 0; + + //------------------------------------------------------------------ + /// Returns a reference to the UnwindTable for this ObjectFile + /// + /// The UnwindTable contains FuncUnwinders objects for any function in + /// this ObjectFile. If a FuncUnwinders object hasn't been created yet + /// (i.e. the function has yet to be unwound in a stack walk), it + /// will be created when requested. Specifically, we do not create + /// FuncUnwinders objects for functions until they are needed. + /// + /// @return + /// Returns the unwind table for this object file. + //------------------------------------------------------------------ + virtual lldb_private::UnwindTable& + GetUnwindTable () { return m_unwind_table; } + + //------------------------------------------------------------------ + /// Similar to Process::GetImageInfoAddress(). + /// + /// Some platforms embed auxiliary structures useful to debuggers in the + /// address space of the inferior process. This method returns the address + /// of such a structure if the information can be resolved via entries in + /// the object file. ELF, for example, provides a means to hook into the + /// runtime linker so that a debugger may monitor the loading and unloading + /// of shared libraries. + /// + /// @return + /// The address of any auxiliary tables, or an invalid address if this + /// object file format does not support or contain such information. + virtual lldb_private::Address + GetImageInfoAddress () { return Address(); } + + //------------------------------------------------------------------ + /// Returns the address of the Entry Point in this object file - if + /// the object file doesn't have an entry point (because it is not an + /// executable file) then an invalid address is returned. + /// + /// @return + /// Returns the entry address for this module. + //------------------------------------------------------------------ + virtual lldb_private::Address + GetEntryPointAddress () { return Address();} + + //------------------------------------------------------------------ + /// Returns the address that represents the header of this object + /// file. + /// + /// The header address is defined as where the header for the object + /// file is that describes the content of the file. If the header + /// doesn't appear in a section that is defined in the object file, + /// an address with no section is returned that has the file offset + /// set in the m_file_offset member of the lldb_private::Address object. + /// + /// @return + /// Returns the entry address for this module. + //------------------------------------------------------------------ + virtual lldb_private::Address + GetHeaderAddress () { return Address(m_memory_addr);} + + + virtual uint32_t + GetNumThreadContexts () + { + return 0; + } + + virtual lldb::RegisterContextSP + GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &thread) + { + return lldb::RegisterContextSP(); + } + + //------------------------------------------------------------------ + /// 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; + + //------------------------------------------------------------------ + /// In cases where the type can't be calculated (elf files), this + /// routine allows someone to explicitly set it. As an example, + /// SymbolVendorELF uses this routine to set eTypeDebugInfo when + /// loading debug link files. + virtual void + SetType (Type type) + { + m_type = type; + } + + //------------------------------------------------------------------ + /// 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; + + //------------------------------------------------------------------ + /// Get the object file version numbers. + /// + /// Many object files have a set of version numbers that describe + /// the version of the executable or shared library. Typically there + /// are major, minor and build, but there may be more. This function + /// will extract the versions from object files if they are available. + /// + /// If \a versions is NULL, or if \a num_versions is 0, the return + /// value will indicate how many version numbers are available in + /// this object file. Then a subsequent call can be made to this + /// function with a value of \a versions and \a num_versions that + /// has enough storage to store some or all version numbers. + /// + /// @param[out] versions + /// A pointer to an array of uint32_t types that is \a num_versions + /// long. If this value is NULL, the return value will indicate + /// how many version numbers are required for a subsequent call + /// to this function so that all versions can be retrieved. If + /// the value is non-NULL, then at most \a num_versions of the + /// existing versions numbers will be filled into \a versions. + /// If there is no version information available, \a versions + /// will be filled with \a num_versions UINT32_MAX values + /// and zero will be returned. + /// + /// @param[in] num_versions + /// The maximum number of entries to fill into \a versions. If + /// this value is zero, then the return value will indicate + /// how many version numbers there are in total so another call + /// to this function can be make with adequate storage in + /// \a versions to get all of the version numbers. If \a + /// num_versions is less than the actual number of version + /// numbers in this object file, only \a num_versions will be + /// filled into \a versions (if \a versions is non-NULL). + /// + /// @return + /// This function always returns the number of version numbers + /// that this object file has regardless of the number of + /// version numbers that were copied into \a versions. + //------------------------------------------------------------------ + virtual uint32_t + GetVersion (uint32_t *versions, uint32_t num_versions) + { + if (versions && num_versions) + { + for (uint32_t i=0; i<num_versions; ++i) + versions[i] = UINT32_MAX; + } + return 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; + } + + // When an object file is in memory, subclasses should try and lock + // the process weak pointer. If the process weak pointer produces a + // valid ProcessSP, then subclasses can call this function to read + // memory. + static lldb::DataBufferSP + ReadMemory (const lldb::ProcessSP &process_sp, + lldb::addr_t addr, + size_t byte_size); + + size_t + GetData (off_t offset, size_t length, DataExtractor &data) const; + + size_t + CopyData (off_t offset, size_t length, void *dst) const; + + size_t + ReadSectionData (const Section *section, + off_t section_offset, + void *dst, + size_t dst_len) const; + size_t + ReadSectionData (const Section *section, + DataExtractor& section_data) const; + + size_t + MemoryMapSectionData (const Section *section, + DataExtractor& section_data) const; + + bool + IsInMemory () const + { + return m_memory_addr != LLDB_INVALID_ADDRESS; + } + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + FileSpec m_file; + Type m_type; + Strata m_strata; + lldb::addr_t m_file_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. + lldb_private::UnwindTable m_unwind_table; /// < Table of FuncUnwinders objects created for this ObjectFile's functions + lldb::ProcessWP m_process_wp; + const lldb::addr_t m_memory_addr; + std::unique_ptr<lldb_private::SectionList> m_sections_ap; + std::unique_ptr<lldb_private::Symtab> m_symtab_ap; + + //------------------------------------------------------------------ + /// Sets the architecture for a module. At present the architecture + /// can only be set if it is invalid. It is not allowed to switch from + /// one concrete architecture to another. + /// + /// @param[in] new_arch + /// The architecture this module will be set to. + /// + /// @return + /// Returns \b true if the architecture was changed, \b + /// false otherwise. + //------------------------------------------------------------------ + bool SetModulesArchitecture (const ArchSpec &new_arch); + +private: + DISALLOW_COPY_AND_ASSIGN (ObjectFile); +}; + +} // namespace lldb_private + +#endif // liblldb_ObjectFile_h_ + diff --git a/include/lldb/Symbol/Symbol.h b/include/lldb/Symbol/Symbol.h new file mode 100644 index 0000000..11c1cc7 --- /dev/null +++ b/include/lldb/Symbol/Symbol.h @@ -0,0 +1,317 @@ +//===-- Symbol.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_Symbol_h_ +#define liblldb_Symbol_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/SymbolContextScope.h" + +namespace lldb_private { + +class Symbol : + public SymbolContextScope +{ +public: + // ObjectFile readers can classify their symbol table entries and searches can be made + // on specific types where the symbol values will have drastically different meanings + // and sorting requirements. + Symbol(); + + Symbol (uint32_t symID, + const char *name, + bool name_is_mangled, + lldb::SymbolType type, + bool external, + bool is_debug, + bool is_trampoline, + bool is_artificial, + const lldb::SectionSP §ion_sp, + lldb::addr_t value, + lldb::addr_t size, + bool size_is_valid, + uint32_t flags); + + Symbol (uint32_t symID, + const char *name, + bool name_is_mangled, + lldb::SymbolType type, + bool external, + bool is_debug, + bool is_trampoline, + bool is_artificial, + const AddressRange &range, + bool size_is_valid, + uint32_t flags); + + Symbol (const Symbol& rhs); + + const Symbol& + operator= (const Symbol& rhs); + + void + Clear(); + + bool + Compare (const ConstString& name, lldb::SymbolType type) const; + + void + Dump (Stream *s, Target *target, uint32_t index) const; + + bool + ValueIsAddress() const; + + //------------------------------------------------------------------ + // Access the address value. Do NOT hand out the AddressRange as an + // object as the byte size of the address range may not be filled in + // and it should be accessed via GetByteSize(). + //------------------------------------------------------------------ + Address & + GetAddress() + { + return m_addr_range.GetBaseAddress(); + } + + //------------------------------------------------------------------ + // Access the address value. Do NOT hand out the AddressRange as an + // object as the byte size of the address range may not be filled in + // and it should be accessed via GetByteSize(). + //------------------------------------------------------------------ + const Address & + GetAddress() const + { + return m_addr_range.GetBaseAddress(); + } + + const ConstString & + GetName () const + { + return m_mangled.GetName(); + } + + uint32_t + GetID() const + { + return m_uid; + } + + void + SetID(uint32_t uid) + { + m_uid = uid; + } + + Mangled& + GetMangled () + { + return m_mangled; + } + + const Mangled& + GetMangled () const + { + return m_mangled; + } + + uint32_t + GetSiblingIndex () const; + + lldb::SymbolType + GetType () const + { + return (lldb::SymbolType)m_type; + } + + void + SetType (lldb::SymbolType type) + { + m_type = (lldb::SymbolType)type; + } + + const char * + GetTypeAsString () const; + + uint32_t + GetFlags () const + { + return m_flags; + } + + void + SetFlags (uint32_t flags) + { + m_flags = flags; + } + + void + GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const; + + bool + IsSynthetic () const + { + return m_is_synthetic; + } + + void + SetIsSynthetic (bool b) + { + m_is_synthetic = b; + } + + + bool + GetSizeIsSynthesized() const + { + return m_size_is_synthesized; + } + + void + SetSizeIsSynthesized(bool b) + { + m_size_is_synthesized = b; + } + + bool + IsDebug () const + { + return m_is_debug; + } + + void + SetDebug (bool b) + { + m_is_debug = b; + } + + bool + IsExternal () const + { + return m_is_external; + } + + void + SetExternal (bool b) + { + m_is_external = b; + } + + bool + IsTrampoline () const; + + bool + IsIndirect () const; + + bool + GetByteSizeIsValid () const + { + return m_size_is_valid; + } + + lldb::addr_t + GetByteSize () const; + + void + SetByteSize (lldb::addr_t size) + { + m_size_is_valid = size > 0; + m_addr_range.SetByteSize(size); + } + + bool + GetSizeIsSibling () const + { + return m_size_is_sibling; + } + + void + SetSizeIsSibling (bool b) + { + m_size_is_sibling = b; + } + +// void +// SetValue (Address &value) +// { +// m_addr_range.GetBaseAddress() = value; +// } +// +// void +// SetValue (const AddressRange &range) +// { +// m_addr_range = range; +// } +// +// void +// SetValue (lldb::addr_t value); +// { +// m_addr_range.GetBaseAddress().SetRawAddress(value); +// } + + // If m_type is "Code" or "Function" then this will return the prologue size + // in bytes, else it will return zero. + uint32_t + GetPrologueByteSize (); + + bool + GetDemangledNameIsSynthesized() const + { + return m_demangled_is_synthesized; + } + void + SetDemangledNameIsSynthesized(bool b) + { + m_demangled_is_synthesized = b; + } + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext (SymbolContext *sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual Symbol * + CalculateSymbolContextSymbol (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext (Stream *s); + +protected: + + uint32_t m_uid; // User ID (usually the original symbol table index) + uint16_t m_type_data; // data specific to m_type + uint16_t m_type_data_resolved:1, // True if the data in m_type_data has already been calculated + m_is_synthetic:1, // non-zero if this symbol is not actually in the symbol table, but synthesized from other info in the object file. + m_is_debug:1, // non-zero if this symbol is debug information in a symbol + m_is_external:1, // non-zero if this symbol is globally visible + m_size_is_sibling:1, // m_size contains the index of this symbol's sibling + m_size_is_synthesized:1,// non-zero if this symbol's size was calculated using a delta between this symbol and the next + m_size_is_valid:1, + m_demangled_is_synthesized:1, // The demangled name was created should not be used for expressions or other lookups + m_type:8; + Mangled m_mangled; // uniqued symbol name/mangled name pair + AddressRange m_addr_range; // Contains the value, or the section offset address when the value is an address in a section, and the size (if any) + uint32_t m_flags; // A copy of the flags from the original symbol table, the ObjectFile plug-in can interpret these +}; + +} // namespace lldb_private + +#endif // liblldb_Symbol_h_ diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h new file mode 100644 index 0000000..5b12ade --- /dev/null +++ b/include/lldb/Symbol/SymbolContext.h @@ -0,0 +1,566 @@ +//===-- SymbolContext.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_SymbolContext_h_ +#define liblldb_SymbolContext_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/LineEntry.h" + +namespace lldb_private { + +class SymbolContextScope; +//---------------------------------------------------------------------- +/// @class SymbolContext SymbolContext.h "lldb/Symbol/SymbolContext.h" +/// @brief Defines a symbol context baton that can be handed other debug +/// core functions. +/// +/// Many 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. Examples of such +/// queries include +/// @li Looking up a load address. +//---------------------------------------------------------------------- +class SymbolContext +{ +public: + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize all pointer members to NULL and all struct members + /// to their default state. + //------------------------------------------------------------------ + SymbolContext (); + + //------------------------------------------------------------------ + /// Construct with an object that knows how to reconstruct its + /// symbol context. + /// + /// @param[in] sc_scope + /// A symbol context scope object that knows how to reconstruct + /// it's context. + //------------------------------------------------------------------ + explicit + SymbolContext (SymbolContextScope *sc_scope); + + //------------------------------------------------------------------ + /// Construct with module, and optional compile unit, function, + /// block, line table, line entry and symbol. + /// + /// Initialize all pointer to the specified values. + /// + /// @param[in] module + /// A Module pointer to the module for this context. + /// + /// @param[in] comp_unit + /// A CompileUnit pointer to the compile unit for this context. + /// + /// @param[in] function + /// A Function pointer to the function for this context. + /// + /// @param[in] block + /// A Block pointer to the deepest block for this context. + /// + /// @param[in] line_entry + /// A LineEntry pointer to the line entry for this context. + /// + /// @param[in] symbol + /// A Symbol pointer to the symbol for this context. + //------------------------------------------------------------------ + explicit + SymbolContext (const lldb::TargetSP &target_sp, + const lldb::ModuleSP &module_sp, + CompileUnit *comp_unit = NULL, + Function *function = NULL, + Block *block = NULL, + LineEntry *line_entry = NULL, + Symbol *symbol = NULL); + + // This version sets the target to a NULL TargetSP if you don't know it. + explicit + SymbolContext (const lldb::ModuleSP &module_sp, + CompileUnit *comp_unit = NULL, + Function *function = NULL, + Block *block = NULL, + LineEntry *line_entry = NULL, + Symbol *symbol = NULL); + + ~SymbolContext (); + //------------------------------------------------------------------ + /// Copy constructor + /// + /// Makes a copy of the another SymbolContext object \a rhs. + /// + /// @param[in] rhs + /// A const SymbolContext object reference to copy. + //------------------------------------------------------------------ + SymbolContext (const SymbolContext& rhs); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// Copies the address value from another SymbolContext object \a + /// rhs into \a this object. + /// + /// @param[in] rhs + /// A const SymbolContext object reference to copy. + /// + /// @return + /// A const SymbolContext object reference to \a this. + //------------------------------------------------------------------ + const SymbolContext& + operator= (const SymbolContext& rhs); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Resets all pointer members to NULL, and clears any class objects + /// to their default state. + //------------------------------------------------------------------ + void + Clear (bool clear_target); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s, Target *target) const; + + //------------------------------------------------------------------ + /// Dump the stop context in this object to a Stream. + /// + /// Dump the best description of this object to the stream. The + /// information displayed depends on the amount and quality of the + /// information in this context. If a module, function, file and + /// line number are available, they will be dumped. If only a + /// module and function or symbol name with offset is available, + /// that will be output. Else just the address at which the target + /// was stopped will be displayed. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] so_addr + /// The resolved section offset address. + //------------------------------------------------------------------ + bool + DumpStopContext (Stream *s, + ExecutionContextScope *exe_scope, + const Address &so_addr, + bool show_fullpaths, + bool show_module, + bool show_inlined_frames) const; + + //------------------------------------------------------------------ + /// Get the address range contained within a symbol context. + /// + /// Address range priority is as follows: + /// - line_entry address range if line_entry is valid and eSymbolContextLineEntry is set in \a scope + /// - block address range if block is not NULL and eSymbolContextBlock is set in \a scope + /// - function address range if function is not NULL and eSymbolContextFunction is set in \a scope + /// - symbol address range if symbol is not NULL and eSymbolContextSymbol is set in \a scope + /// + /// @param[in] scope + /// A mask of symbol context bits telling this function which + /// address ranges it can use when trying to extract one from + /// the valid (non-NULL) symbol context classes. + /// + /// @param[in] range_idx + /// The address range index to grab. Since many functions and + /// blocks are not always contiguous, they may have more than + /// one address range. + /// + /// @param[in] use_inline_block_range + /// If \a scope has the eSymbolContextBlock bit set, and there + /// is a valid block in the symbol context, return the block + /// address range for the containing inline function block, not + /// the deepest most block. This allows us to extract information + /// for the address range of the inlined function block, not + /// the deepest lexical block. + /// + /// @param[out] range + /// An address range object that will be filled in if \b true + /// is returned. + /// + /// @return + /// \b True if this symbol context contains items that describe + /// an address range, \b false otherwise. + //------------------------------------------------------------------ + bool + GetAddressRange (uint32_t scope, + uint32_t range_idx, + bool use_inline_block_range, + AddressRange &range) const; + + + void + GetDescription(Stream *s, + lldb::DescriptionLevel level, + Target *target) const; + + uint32_t + GetResolvedMask () const; + + + //------------------------------------------------------------------ + /// Find a block that defines the function represented by this + /// symbol context. + /// + /// If this symbol context points to a block that is an inlined + /// function, or is contained within an inlined function, the block + /// that defines the inlined function is returned. + /// + /// If this symbol context has no block in it, or the block is not + /// itself an inlined function block or contained within one, we + /// return the top level function block. + /// + /// This is a handy function to call when you want to get the block + /// whose variable list will include the arguments for the function + /// that is represented by this symbol context (whether the function + /// is an inline function or not). + /// + /// @return + /// The block object pointer that defines the function that is + /// represented by this symbol context object, NULL otherwise. + //------------------------------------------------------------------ + Block * + GetFunctionBlock (); + + + //------------------------------------------------------------------ + /// If this symbol context represents a function that is a method, + /// return true and provide information about the method. + /// + /// @param[out] language + /// If \b true is returned, the language for the method. + /// + /// @param[out] is_instance_method + /// If \b true is returned, \b true if this is a instance method, + /// \b false if this is a static/class function. + /// + /// @param[out] language_object_name + /// If \b true is returned, the name of the artificial variable + /// for the language ("this" for C++, "self" for ObjC). + /// + /// @return + /// \b True if this symbol context represents a function that + /// is a method of a class, \b false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionMethodInfo (lldb::LanguageType &language, + bool &is_instance_method, + ConstString &language_object_name); + + //------------------------------------------------------------------ + /// Find a name of the innermost function for the symbol context. + /// + /// For instance, if the symbol context contains an inlined block, + /// it will return the inlined function name. + /// + /// @param[in] prefer_mangled + /// if \btrue, then the mangled name will be returned if there + /// is one. Otherwise the unmangled name will be returned if it + /// is available. + /// + /// @return + /// The name of the function represented by this symbol context. + //------------------------------------------------------------------ + ConstString + GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled) const; + + + //------------------------------------------------------------------ + /// Get the line entry that corresponds to the function. + /// + /// If the symbol context contains an inlined block, the line entry + /// for the start address of the inlined function will be returned, + /// otherwise the line entry for the start address of the function + /// will be returned. This can be used after doing a + /// Module::FindFunctions(...) or ModuleList::FindFunctions(...) + /// call in order to get the correct line table information for + /// the symbol context. + /// it will return the inlined function name. + /// + /// @param[in] prefer_mangled + /// if \btrue, then the mangled name will be returned if there + /// is one. Otherwise the unmangled name will be returned if it + /// is available. + /// + /// @return + /// The name of the function represented by this symbol context. + //------------------------------------------------------------------ + LineEntry + GetFunctionStartLineEntry () const; + + //------------------------------------------------------------------ + /// Find the block containing the inlined block that contains this block. + /// + /// For instance, if the symbol context contains an inlined block, + /// it will return the inlined function name. + /// + /// @param[in] curr_frame_pc + /// The address within the block of this object. + /// + /// @param[out] next_frame_sc + /// A new symbol context that does what the title says it does. + /// + /// @param[out] next_frame_addr + /// This is what you should report as the PC in \a next_frame_sc. + /// + /// @return + /// \b true if this SymbolContext specifies a block contained in an + /// inlined block. If this returns \b true, \a next_frame_sc and + /// \a next_frame_addr will be filled in correctly. + //------------------------------------------------------------------ + bool + GetParentOfInlinedScope (const Address &curr_frame_pc, + SymbolContext &next_frame_sc, + Address &inlined_frame_addr) const; + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + lldb::TargetSP target_sp; ///< The Target for a given query + lldb::ModuleSP module_sp; ///< The Module for a given query + CompileUnit * comp_unit; ///< The CompileUnit for a given query + Function * function; ///< The Function for a given query + Block * block; ///< The Block for a given query + LineEntry line_entry; ///< The LineEntry for a given query + Symbol * symbol; ///< The Symbol for a given query +}; + + +class SymbolContextSpecifier +{ +public: + typedef enum SpecificationType + { + eNothingSpecified = 0, + eModuleSpecified = 1 << 0, + eFileSpecified = 1 << 1, + eLineStartSpecified = 1 << 2, + eLineEndSpecified = 1 << 3, + eFunctionSpecified = 1 << 4, + eClassOrNamespaceSpecified = 1 << 5, + eAddressRangeSpecified = 1 << 6 + } SpecificationType; + + // This one produces a specifier that matches everything... + SymbolContextSpecifier (const lldb::TargetSP& target_sp); + + ~SymbolContextSpecifier(); + + bool + AddSpecification (const char *spec_string, SpecificationType type); + + bool + AddLineSpecification (uint32_t line_no, SpecificationType type); + + void + Clear(); + + bool + SymbolContextMatches(SymbolContext &sc); + + bool + AddressMatches(lldb::addr_t addr); + + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + +private: + lldb::TargetSP m_target_sp; + std::string m_module_spec; + lldb::ModuleSP m_module_sp; + std::unique_ptr<FileSpec> m_file_spec_ap; + size_t m_start_line; + size_t m_end_line; + std::string m_function_spec; + std::string m_class_name; + std::unique_ptr<AddressRange> m_address_range_ap; + uint32_t m_type; // Or'ed bits from SpecificationType + +}; + +//---------------------------------------------------------------------- +/// @class SymbolContextList SymbolContext.h "lldb/Symbol/SymbolContext.h" +/// @brief Defines a list of symbol context objects. +/// +/// This class provides a common structure that can be used to contain +/// the result of a query that can contain a multiple results. Examples +/// of such queries include: +/// @li Looking up a function by name. +/// @li Finding all addressses for a specified file and line number. +//---------------------------------------------------------------------- +class SymbolContextList +{ +public: + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize with an empty list. + //------------------------------------------------------------------ + SymbolContextList (); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~SymbolContextList (); + + //------------------------------------------------------------------ + /// Append a new symbol context to the list. + /// + /// @param[in] sc + /// A symbol context to append to the list. + //------------------------------------------------------------------ + void + Append (const SymbolContext& sc); + + void + Append (const SymbolContextList& sc_list); + + bool + AppendIfUnique (const SymbolContext& sc, + bool merge_symbol_into_function); + + bool + MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc, + uint32_t start_idx = 0, + uint32_t stop_idx = UINT32_MAX); + + uint32_t + AppendIfUnique (const SymbolContextList& sc_list, + bool merge_symbol_into_function); + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Clears the symbol context list. + //------------------------------------------------------------------ + void + Clear(); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of each symbol context in + /// the list to the supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump(Stream *s, Target *target) const; + + //------------------------------------------------------------------ + /// Get accessor for a symbol context at index \a idx. + /// + /// Dump a description of the contents of each symbol context in + /// the list to the supplied stream \a s. + /// + /// @param[in] idx + /// The zero based index into the symbol context list. + /// + /// @param[out] sc + /// A reference to the symbol context to fill in. + /// + /// @return + /// Returns \b true if \a idx was a valid index into this + /// symbol context list and \a sc was filled in, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + GetContextAtIndex(size_t idx, SymbolContext& sc) const; + + //------------------------------------------------------------------ + /// Direct reference accessor for a symbol context at index \a idx. + /// + /// The index \a idx must be a valid index, no error checking will + /// be done to ensure that it is valid. + /// + /// @param[in] idx + /// The zero based index into the symbol context list. + /// + /// @return + /// A const reference to the symbol context to fill in. + //------------------------------------------------------------------ + SymbolContext& + operator [] (size_t idx) + { + return m_symbol_contexts[idx]; + } + + const SymbolContext& + operator [] (size_t idx) const + { + return m_symbol_contexts[idx]; + } + + //------------------------------------------------------------------ + /// Get accessor for the last symbol context in the list. + /// + /// @param[out] sc + /// A reference to the symbol context to fill in. + /// + /// @return + /// Returns \b true if \a sc was filled in, \b false if the + /// list is empty. + //------------------------------------------------------------------ + bool + GetLastContext(SymbolContext& sc) const; + + bool + RemoveContextAtIndex (size_t idx); + //------------------------------------------------------------------ + /// Get accessor for a symbol context list size. + /// + /// @return + /// Returns the number of symbol context objects in the list. + //------------------------------------------------------------------ + uint32_t + GetSize() const; + + uint32_t + NumLineEntriesWithLine (uint32_t line) const; + + void + GetDescription(Stream *s, + lldb::DescriptionLevel level, + Target *target) const; + +protected: + typedef std::vector<SymbolContext> collection; ///< The collection type for the list. + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + collection m_symbol_contexts; ///< The list of symbol contexts. +}; + +bool operator== (const SymbolContext& lhs, const SymbolContext& rhs); +bool operator!= (const SymbolContext& lhs, const SymbolContext& rhs); + +bool operator== (const SymbolContextList& lhs, const SymbolContextList& rhs); +bool operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs); + +} // namespace lldb_private + +#endif // liblldb_SymbolContext_h_ diff --git a/include/lldb/Symbol/SymbolContextScope.h b/include/lldb/Symbol/SymbolContextScope.h new file mode 100644 index 0000000..693cc01 --- /dev/null +++ b/include/lldb/Symbol/SymbolContextScope.h @@ -0,0 +1,137 @@ +//===-- SymbolContextScope.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_SymbolContextScope_h_ +#define liblldb_SymbolContextScope_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class SymbolContextScope SymbolContextScope.h "lldb/Symbol/SymbolContextScope.h" +/// @brief Inherit from this if your object is part of a symbol context +/// and can reconstruct its symbol context. +/// +/// Many objects that are part of a symbol context that have pointers +/// back to parent objects that own them. Any members of a symbol +/// context that, once they are built, will not go away, can inherit +/// from this pure virtual class and can then reconstruct their symbol +/// context without having to keep a complete SymbolContext object in +/// the object. +/// +/// Examples of these objects include: +/// @li Module +/// @li CompileUnit +/// @li Function +/// @li Block +/// @li Symbol +/// +/// Other objects can store a "SymbolContextScope *" using any pointers +/// to one of the above objects. This allows clients to hold onto a +/// pointer that uniquely will identify a symbol context. Those clients +/// can then always reconstruct the symbol context using the pointer, or +/// use it to uniquely identify a symbol context for an object. +/// +/// Example objects include that currently use "SymbolContextScope *" +/// objects include: +/// @li Variable objects that can reconstruct where they are scoped +/// by making sure the SymbolContextScope * comes from the scope +/// in which the variable was declared. If a variable is a global, +/// the appropriate CompileUnit * will be used when creating the +/// variable. A static function variables, can the Block scope +/// in which the variable is defined. Function arguments can use +/// the Function object as their scope. The SymbolFile parsers +/// will set these correctly as the variables are parsed. +/// @li Type objects that know exactly in which scope they +/// originated much like the variables above. +/// @li StackID objects that are able to know that if the CFA +/// (stack pointer at the beginning of a function) and the +/// start PC for the function/symbol and the SymbolContextScope +/// pointer (a unique pointer that identifies a symbol context +/// location) match within the same thread, that the stack +/// frame is the same as the previous stack frame. +/// +/// Objects that adhere to this protocol can reconstruct enough of a +/// symbol context to allow functions that take a symbol context to be +/// called. Lists can also be created using a SymbolContextScope* and +/// and object pairs that allow large collections of objects to be +/// passed around with minimal overhead. +//---------------------------------------------------------------------- +class SymbolContextScope +{ +public: + virtual + ~SymbolContextScope () {} + + //------------------------------------------------------------------ + /// Reconstruct the object's symbolc context into \a sc. + /// + /// The object should fill in as much of the SymbolContext as it + /// can so function calls that require a symbol context can be made + /// for the given object. + /// + /// @param[out] sc + /// A symbol context object pointer that gets filled in. + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext (SymbolContext *sc) = 0; + + + virtual lldb::ModuleSP + CalculateSymbolContextModule () + { + return lldb::ModuleSP(); + } + + virtual CompileUnit * + CalculateSymbolContextCompileUnit () + { + return NULL; + } + + virtual Function * + CalculateSymbolContextFunction () + { + return NULL; + } + + virtual Block * + CalculateSymbolContextBlock () + { + return NULL; + } + + virtual Symbol * + CalculateSymbolContextSymbol () + { + return NULL; + } + + //------------------------------------------------------------------ + /// Dump the object's symbolc context to the stream \a s. + /// + /// The object should dump its symbol context to the stream \a s. + /// This function is widely used in the DumpDebug and verbose output + /// for lldb objets. + /// + /// @param[in] s + /// The stream to which to dump the object's symbol context. + //------------------------------------------------------------------ + virtual void + DumpSymbolContext (Stream *s) = 0; +}; + +} // namespace lldb_private + +#endif // liblldb_SymbolContextScope_h_ diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h new file mode 100644 index 0000000..5b774e3 --- /dev/null +++ b/include/lldb/Symbol/SymbolFile.h @@ -0,0 +1,167 @@ +//===-- SymbolFile.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_SymbolFile_h_ +#define liblldb_SymbolFile_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" +#include "lldb/Symbol/Type.h" + +namespace lldb_private { + +class SymbolFile : + public PluginInterface +{ +public: + //------------------------------------------------------------------ + // Symbol file ability bits. + // + // Each symbol file can claim to support one or more symbol file + // abilities. These get returned from SymbolFile::GetAbilities(). + // These help us to determine which plug-in will be best to load + // the debug information found in files. + //------------------------------------------------------------------ + enum Abilities + { + CompileUnits = (1u << 0), + LineTables = (1u << 1), + Functions = (1u << 2), + Blocks = (1u << 3), + GlobalVariables = (1u << 4), + LocalVariables = (1u << 5), + VariableTypes = (1u << 6), + kAllAbilities =((1u << 7) - 1u) + }; + + static SymbolFile * + FindPlugin (ObjectFile* obj_file); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SymbolFile(ObjectFile* obj_file) : + m_obj_file(obj_file), + m_abilities(0), + m_calculated_abilities(false) + { + } + + virtual + ~SymbolFile() + { + } + + //------------------------------------------------------------------ + /// Get a mask of what this symbol file supports for the object file + /// that it was constructed with. + /// + /// Each symbol file gets to respond with a mask of abilities that + /// it supports for each object file. This happens when we are + /// trying to figure out which symbol file plug-in will get used + /// for a given object file. The plug-in that resoonds with the + /// best mix of "SymbolFile::Abilities" bits set, will get chosen to + /// be the symbol file parser. This allows each plug-in to check for + /// sections that contain data a symbol file plug-in would need. For + /// example the DWARF plug-in requires DWARF sections in a file that + /// contain debug information. If the DWARF plug-in doesn't find + /// these sections, it won't respond with many ability bits set, and + /// we will probably fall back to the symbol table SymbolFile plug-in + /// which uses any information in the symbol table. Also, plug-ins + /// might check for some specific symbols in a symbol table in the + /// case where the symbol table contains debug information (STABS + /// and COFF). Not a lot of work should happen in these functions + /// as the plug-in might not get selected due to another plug-in + /// having more abilities. Any initialization work should be saved + /// for "void SymbolFile::InitializeObject()" which will get called + /// on the SymbolFile object with the best set of abilities. + /// + /// @return + /// A uint32_t mask containing bits from the SymbolFile::Abilities + /// enumeration. Any bits that are set represent an ability that + /// this symbol plug-in can parse from the object file. + ///------------------------------------------------------------------ + uint32_t GetAbilities () + { + if (!m_calculated_abilities) + { + m_abilities = CalculateAbilities(); + m_calculated_abilities = true; + } + + return m_abilities; + } + + virtual uint32_t CalculateAbilities() = 0; + + //------------------------------------------------------------------ + /// Initialize the SymbolFile object. + /// + /// The SymbolFile object with the best set of abilities (detected + /// in "uint32_t SymbolFile::GetAbilities()) will have this function + /// called if it is chosen to parse an object file. More complete + /// initialization can happen in this function which will get called + /// prior to any other functions in the SymbolFile protocol. + //------------------------------------------------------------------ + virtual void InitializeObject() {} + + //------------------------------------------------------------------ + // Compile Unit function calls + //------------------------------------------------------------------ + // Approach 1 - iterator + virtual uint32_t GetNumCompileUnits() = 0; + virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) = 0; + + virtual lldb::LanguageType ParseCompileUnitLanguage (const SymbolContext& sc) = 0; + virtual size_t ParseCompileUnitFunctions (const SymbolContext& sc) = 0; + virtual bool ParseCompileUnitLineTable (const SymbolContext& sc) = 0; + virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) = 0; + virtual size_t ParseFunctionBlocks (const SymbolContext& sc) = 0; + virtual size_t ParseTypes (const SymbolContext& sc) = 0; + virtual size_t ParseVariablesForContext (const SymbolContext& sc) = 0; + virtual Type* ResolveTypeUID (lldb::user_id_t type_uid) = 0; + virtual bool ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) = 0; + virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) { return NULL; } + virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) { return NULL; } + virtual uint32_t ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) = 0; + virtual uint32_t ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) = 0; + virtual uint32_t FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) = 0; + virtual uint32_t FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) = 0; + virtual uint32_t FindFunctions (const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) = 0; + virtual uint32_t FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) = 0; + virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types) = 0; +// virtual uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0; + virtual TypeList * GetTypeList (); + virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope, + uint32_t type_mask, + lldb_private::TypeList &type_list) = 0; + virtual ClangASTContext & + GetClangASTContext (); + virtual ClangNamespaceDecl + FindNamespace (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *parent_namespace_decl) = 0; + + ObjectFile* GetObjectFile() { return m_obj_file; } + const ObjectFile* GetObjectFile() const { return m_obj_file; } + +protected: + ObjectFile* m_obj_file; // The object file that symbols can be extracted from. + uint32_t m_abilities; + bool m_calculated_abilities; +private: + DISALLOW_COPY_AND_ASSIGN (SymbolFile); +}; + + +} // namespace lldb_private + +#endif // liblldb_SymbolFile_h_ diff --git a/include/lldb/Symbol/SymbolVendor.h b/include/lldb/Symbol/SymbolVendor.h new file mode 100644 index 0000000..0eeea4e --- /dev/null +++ b/include/lldb/Symbol/SymbolVendor.h @@ -0,0 +1,207 @@ +//===-- SymbolVendor.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_SymbolVendor_h_ +#define liblldb_SymbolVendor_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" +#include "lldb/Symbol/TypeList.h" + + +namespace lldb_private { + +//---------------------------------------------------------------------- +// The symbol vendor class is designed to abstract the process of +// searching for debug information for a given module. Platforms can +// subclass this class and provide extra ways to find debug information. +// Examples would be a subclass that would allow for locating a stand +// alone debug file, parsing debug maps, or runtime data in the object +// files. A symbol vendor can use multiple sources (SymbolFile +// objects) to provide the information and only parse as deep as needed +// in order to provide the information that is requested. +//---------------------------------------------------------------------- +class SymbolVendor : + public ModuleChild, + public PluginInterface +{ +public: + static SymbolVendor* + FindPlugin (const lldb::ModuleSP &module_sp, + Stream *feedback_strm); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SymbolVendor(const lldb::ModuleSP &module_sp); + + virtual + ~SymbolVendor(); + + void + AddSymbolFileRepresentation(const lldb::ObjectFileSP &objfile_sp); + + virtual void + Dump(Stream *s); + + virtual lldb::LanguageType + ParseCompileUnitLanguage (const SymbolContext& sc); + + virtual size_t + ParseCompileUnitFunctions (const SymbolContext& sc); + + virtual bool + ParseCompileUnitLineTable (const SymbolContext& sc); + + virtual bool + ParseCompileUnitSupportFiles (const SymbolContext& sc, + FileSpecList& support_files); + + virtual size_t + ParseFunctionBlocks (const SymbolContext& sc); + + virtual size_t + ParseTypes (const SymbolContext& sc); + + virtual size_t + ParseVariablesForContext (const SymbolContext& sc); + + virtual Type* + ResolveTypeUID(lldb::user_id_t type_uid); + + virtual uint32_t + ResolveSymbolContext (const Address& so_addr, + uint32_t resolve_scope, + SymbolContext& sc); + + virtual uint32_t + ResolveSymbolContext (const FileSpec& file_spec, + uint32_t line, + bool check_inlines, + uint32_t resolve_scope, + SymbolContextList& sc_list); + + virtual size_t + FindGlobalVariables (const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + size_t max_matches, + VariableList& variables); + + virtual size_t + FindGlobalVariables (const RegularExpression& regex, + bool append, + size_t max_matches, + VariableList& variables); + + virtual size_t + FindFunctions (const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + uint32_t name_type_mask, + bool include_inlines, + bool append, + SymbolContextList& sc_list); + + virtual size_t + FindFunctions (const RegularExpression& regex, + bool include_inlines, + bool append, + SymbolContextList& sc_list); + + virtual size_t + FindTypes (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + size_t max_matches, + TypeList& types); + + virtual ClangNamespaceDecl + FindNamespace (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *parent_namespace_decl); + + virtual size_t + GetNumCompileUnits(); + + virtual bool + SetCompileUnitAtIndex (size_t cu_idx, + const lldb::CompUnitSP &cu_sp); + + virtual lldb::CompUnitSP + GetCompileUnitAtIndex(size_t idx); + + TypeList& + GetTypeList() + { + return m_type_list; + } + + const TypeList& + GetTypeList() const + { + return m_type_list; + } + + virtual size_t + GetTypes (SymbolContextScope *sc_scope, + uint32_t type_mask, + TypeList &type_list); + + SymbolFile * + GetSymbolFile() + { + return m_sym_file_ap.get(); + } + + // Get module unified section list symbol table. + virtual Symtab * + GetSymtab (); + + // Clear module unified section list symbol table. + virtual void + ClearSymtab (); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from SymbolVendor can see and modify these + //------------------------------------------------------------------ + typedef std::vector<lldb::CompUnitSP> CompileUnits; + typedef CompileUnits::iterator CompileUnitIter; + typedef CompileUnits::const_iterator CompileUnitConstIter; + + TypeList m_type_list; // Uniqued types for all parsers owned by this module + CompileUnits m_compile_units; // The current compile units + lldb::ObjectFileSP m_objfile_sp; // Keep a reference to the object file in case it isn't the same as the module object file (debug symbols in a separate file) + std::unique_ptr<SymbolFile> m_sym_file_ap; // A single symbol file. Subclasses can add more of these if needed. + +private: + //------------------------------------------------------------------ + // For SymbolVendor only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (SymbolVendor); +}; + + +} // namespace lldb_private + +#endif // liblldb_SymbolVendor_h_ diff --git a/include/lldb/Symbol/Symtab.h b/include/lldb/Symbol/Symtab.h new file mode 100644 index 0000000..666c3b5 --- /dev/null +++ b/include/lldb/Symbol/Symtab.h @@ -0,0 +1,160 @@ +//===-- Symtab.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_Symtab_h_ +#define liblldb_Symtab_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/Symbol.h" + +namespace lldb_private { + +class Symtab +{ +public: + typedef std::vector<uint32_t> IndexCollection; + typedef UniqueCStringMap<uint32_t> NameToIndexMap; + + typedef enum Debug { + eDebugNo, // Not a debug symbol + eDebugYes, // A debug symbol + eDebugAny + } Debug; + + typedef enum Visibility { + eVisibilityAny, + eVisibilityExtern, + eVisibilityPrivate + } Visibility; + + Symtab(ObjectFile *objfile); + ~Symtab(); + + void Reserve (size_t count); + Symbol * Resize (size_t count); + uint32_t AddSymbol(const Symbol& symbol); + size_t GetNumSymbols() const; + void Dump(Stream *s, Target *target, SortOrder sort_type); + void Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const; + uint32_t GetIndexForSymbol (const Symbol *symbol) const; + Mutex & GetMutex () + { + return m_mutex; + } + Symbol * FindSymbolByID (lldb::user_id_t uid) const; + Symbol * SymbolAtIndex (size_t idx); + const Symbol * SymbolAtIndex (size_t idx) const; + Symbol * FindSymbolWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t &start_idx); + uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; + uint32_t AppendSymbolIndexesWithTypeAndFlagsValue (lldb::SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; + uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& matches, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; + uint32_t AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, lldb::SymbolType symbol_type, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, std::vector<uint32_t>& indexes); + uint32_t AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes); + size_t FindAllSymbolsWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes); + size_t FindAllSymbolsWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes); + size_t FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes); + Symbol * FindFirstSymbolWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility); + Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes); + Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr); + size_t FindFunctionSymbols (const ConstString &name, uint32_t name_type_mask, SymbolContextList& sc_list); + void CalculateSymbolSizes (); + + void SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const; + + static void DumpSymbolHeader (Stream *s); + + + void Finalize () + { + // Shrink to fit the symbols so we don't waste memory + if (m_symbols.capacity() > m_symbols.size()) + { + collection new_symbols (m_symbols.begin(), m_symbols.end()); + m_symbols.swap (new_symbols); + } + } + + void AppendSymbolNamesToMap (const IndexCollection &indexes, + bool add_demangled, + bool add_mangled, + NameToIndexMap &name_to_index_map) const; + +protected: + typedef std::vector<Symbol> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> FileRangeToIndexMap; + void InitNameIndexes (); + void InitAddressIndexes (); + + ObjectFile * m_objfile; + collection m_symbols; + FileRangeToIndexMap m_file_addr_to_index; + UniqueCStringMap<uint32_t> m_name_to_index; + UniqueCStringMap<uint32_t> m_basename_to_index; + UniqueCStringMap<uint32_t> m_method_to_index; + UniqueCStringMap<uint32_t> m_selector_to_index; + mutable Mutex m_mutex; // Provide thread safety for this symbol table + bool m_file_addr_to_index_computed:1, + m_name_indexes_computed:1; +private: + + bool + CheckSymbolAtIndex (size_t idx, Debug symbol_debug_type, Visibility symbol_visibility) const + { + switch (symbol_debug_type) + { + case eDebugNo: + if (m_symbols[idx].IsDebug() == true) + return false; + break; + + case eDebugYes: + if (m_symbols[idx].IsDebug() == false) + return false; + break; + + case eDebugAny: + break; + } + + switch (symbol_visibility) + { + case eVisibilityAny: + return true; + + case eVisibilityExtern: + return m_symbols[idx].IsExternal(); + + case eVisibilityPrivate: + return !m_symbols[idx].IsExternal(); + } + return false; + } + + void + SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, + SymbolContextList &sc_list); + + DISALLOW_COPY_AND_ASSIGN (Symtab); +}; + +} // namespace lldb_private + +#endif // liblldb_Symtab_h_ diff --git a/include/lldb/Symbol/TaggedASTType.h b/include/lldb/Symbol/TaggedASTType.h new file mode 100644 index 0000000..c44a535 --- /dev/null +++ b/include/lldb/Symbol/TaggedASTType.h @@ -0,0 +1,61 @@ +//===-- TaggedASTType.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_TaggedASTType_h_ +#define liblldb_TaggedASTType_h_ + +#include "lldb/Symbol/ClangASTType.h" + +namespace lldb_private +{ + +// For cases in which there are multiple classes of types that are not +// interchangeable, to allow static type checking. +template <unsigned int C> class TaggedASTType : public ClangASTType +{ +public: + TaggedASTType (const ClangASTType &clang_type) : + ClangASTType(clang_type) + { + } + + TaggedASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) : + ClangASTType(ast_context, type) + { + } + + TaggedASTType (const TaggedASTType<C> &tw) : + ClangASTType(tw) + { + } + + TaggedASTType () : + ClangASTType() + { + } + + virtual + ~TaggedASTType() + { + } + + TaggedASTType<C> &operator= (const TaggedASTType<C> &tw) + { + ClangASTType::operator= (tw); + return *this; + } +}; + +// Commonly-used tagged types, so code using them is interoperable +typedef TaggedASTType<0> TypeFromParser; +typedef TaggedASTType<1> TypeFromUser; + +} + +#endif diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h new file mode 100644 index 0000000..50b22fe --- /dev/null +++ b/include/lldb/Symbol/Type.h @@ -0,0 +1,596 @@ +//===-- Type.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_Type_h_ +#define liblldb_Type_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/Declaration.h" + +#include <set> + +namespace lldb_private { + +class SymbolFileType : + public std::enable_shared_from_this<SymbolFileType>, + public UserID + { + public: + SymbolFileType (SymbolFile &symbol_file, lldb::user_id_t uid) : + UserID (uid), + m_symbol_file (symbol_file) + { + } + + ~SymbolFileType () + { + } + + Type * + operator->() + { + return GetType (); + } + + Type * + GetType (); + + protected: + SymbolFile &m_symbol_file; + lldb::TypeSP m_type_sp; + }; + +class Type : + public std::enable_shared_from_this<Type>, + public UserID +{ +public: + typedef enum EncodingDataTypeTag + { + eEncodingInvalid, + eEncodingIsUID, ///< This type is the type whose UID is m_encoding_uid + eEncodingIsConstUID, ///< This type is the type whose UID is m_encoding_uid with the const qualifier added + eEncodingIsRestrictUID, ///< This type is the type whose UID is m_encoding_uid with the restrict qualifier added + eEncodingIsVolatileUID, ///< This type is the type whose UID is m_encoding_uid with the volatile qualifier added + eEncodingIsTypedefUID, ///< This type is pointer to a type whose UID is m_encoding_uid + eEncodingIsPointerUID, ///< This type is pointer to a type whose UID is m_encoding_uid + eEncodingIsLValueReferenceUID, ///< This type is L value reference to a type whose UID is m_encoding_uid + eEncodingIsRValueReferenceUID, ///< This type is R value reference to a type whose UID is m_encoding_uid + eEncodingIsSyntheticUID + } EncodingDataType; + + typedef enum ResolveStateTag + { + eResolveStateUnresolved = 0, + eResolveStateForward = 1, + eResolveStateLayout = 2, + eResolveStateFull = 3 + } ResolveState; + + Type (lldb::user_id_t uid, + SymbolFile* symbol_file, + const ConstString &name, + uint64_t byte_size, + SymbolContextScope *context, + lldb::user_id_t encoding_uid, + EncodingDataType encoding_uid_type, + const Declaration& decl, + const ClangASTType &clang_qual_type, + ResolveState clang_type_resolve_state); + + // This makes an invalid type. Used for functions that return a Type when they + // get an error. + Type(); + + Type (const Type &rhs); + + const Type& + operator= (const Type& rhs); + + void + Dump(Stream *s, bool show_context); + + void + DumpTypeName(Stream *s); + + + void + GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name); + + SymbolFile * + GetSymbolFile() + { + return m_symbol_file; + } + const SymbolFile * + GetSymbolFile() const + { + return m_symbol_file; + } + + TypeList* + GetTypeList(); + + const ConstString& + GetName(); + + uint64_t + GetByteSize(); + + uint32_t + GetNumChildren (bool omit_empty_base_classes); + + bool + IsAggregateType (); + + bool + IsValidType () + { + return m_encoding_uid_type != eEncodingInvalid; + } + + bool + IsTypedef () + { + return m_encoding_uid_type == eEncodingIsTypedefUID; + } + + lldb::TypeSP + GetTypedefType(); + + const ConstString & + GetName () const + { + return m_name; + } + + ConstString + GetQualifiedName (); + + void + DumpValue(ExecutionContext *exe_ctx, + Stream *s, + const DataExtractor &data, + uint32_t data_offset, + bool show_type, + bool show_summary, + bool verbose, + lldb::Format format = lldb::eFormatDefault); + + bool + DumpValueInMemory(ExecutionContext *exe_ctx, + Stream *s, + lldb::addr_t address, + AddressType address_type, + bool show_types, + bool show_summary, + bool verbose); + + bool + ReadFromMemory (ExecutionContext *exe_ctx, + lldb::addr_t address, + AddressType address_type, + DataExtractor &data); + + bool + WriteToMemory (ExecutionContext *exe_ctx, + lldb::addr_t address, + AddressType address_type, + DataExtractor &data); + + bool + GetIsDeclaration() const; + + void + SetIsDeclaration(bool b); + + bool + GetIsExternal() const; + + void + SetIsExternal(bool b); + + lldb::Format + GetFormat (); + + lldb::Encoding + GetEncoding (uint64_t &count); + + SymbolContextScope * + GetSymbolContextScope() + { + return m_context; + } + const SymbolContextScope * + GetSymbolContextScope() const + { + return m_context; + } + void + SetSymbolContextScope(SymbolContextScope *context) + { + m_context = context; + } + + const lldb_private::Declaration & + GetDeclaration () const; + + // Get the clang type, and resolve definitions for any + // class/struct/union/enum types completely. + ClangASTType + GetClangFullType (); + + // Get the clang type, and resolve definitions enough so that the type could + // have layout performed. This allows ptrs and refs to class/struct/union/enum + // types remain forward declarations. + ClangASTType + GetClangLayoutType (); + + // Get the clang type and leave class/struct/union/enum types as forward + // declarations if they haven't already been fully defined. + ClangASTType + GetClangForwardType (); + + ClangASTContext & + GetClangASTContext (); + + static int + Compare(const Type &a, const Type &b); + + // From a fully qualified typename, split the type into the type basename + // and the remaining type scope (namespaces/classes). + static bool + GetTypeScopeAndBasename (const char* &name_cstr, + std::string &scope, + std::string &basename, + lldb::TypeClass &type_class); + void + SetEncodingType (Type *encoding_type) + { + m_encoding_type = encoding_type; + } + + uint32_t + GetEncodingMask (); + + ClangASTType + CreateClangTypedefType (Type *typedef_type, Type *base_type); + + bool + IsRealObjCClass(); + + bool + IsCompleteObjCClass() + { + return m_flags.is_complete_objc_class; + } + + void + SetIsCompleteObjCClass(bool is_complete_objc_class) + { + m_flags.is_complete_objc_class = is_complete_objc_class; + } + +protected: + ConstString m_name; + SymbolFile *m_symbol_file; + SymbolContextScope *m_context; // The symbol context in which this type is defined + Type *m_encoding_type; + lldb::user_id_t m_encoding_uid; + EncodingDataType m_encoding_uid_type; + uint64_t m_byte_size; + Declaration m_decl; + ClangASTType m_clang_type; + + struct Flags { + ResolveState clang_type_resolve_state : 2; + bool is_complete_objc_class : 1; + } m_flags; + + Type * + GetEncodingType (); + + bool + ResolveClangType (ResolveState clang_type_resolve_state); +}; + + +/// +/// Sometimes you can find the name of the type corresponding to an object, but we don't have debug +/// information for it. If that is the case, you can return one of these objects, and then if it +/// has a full type, you can use that, but if not at least you can print the name for informational +/// purposes. +/// + +class TypeAndOrName +{ +public: + TypeAndOrName (); + TypeAndOrName (lldb::TypeSP &type_sp); + TypeAndOrName (const char *type_str); + TypeAndOrName (const TypeAndOrName &rhs); + TypeAndOrName (ConstString &type_const_string); + + TypeAndOrName & + operator= (const TypeAndOrName &rhs); + + bool + operator==(const TypeAndOrName &other) const; + + bool + operator!=(const TypeAndOrName &other) const; + + ConstString GetName () const; + + lldb::TypeSP + GetTypeSP () const + { + return m_type_sp; + } + + void + SetName (const ConstString &type_name); + + void + SetName (const char *type_name_cstr); + + void + SetTypeSP (lldb::TypeSP type_sp); + + bool + IsEmpty (); + + bool + HasName (); + + bool + HasTypeSP (); + + void + Clear (); + + operator + bool () + { + return !IsEmpty(); + } + +private: + lldb::TypeSP m_type_sp; + ConstString m_type_name; +}; + +// the two classes here are used by the public API as a backend to +// the SBType and SBTypeList classes + +class TypeImpl +{ +public: + + TypeImpl() : + m_clang_ast_type(), + m_type_sp() + { + } + + TypeImpl(const TypeImpl& rhs) : + m_clang_ast_type(rhs.m_clang_ast_type), + m_type_sp(rhs.m_type_sp) + { + } + + TypeImpl(const lldb_private::ClangASTType& type); + + TypeImpl(const lldb::TypeSP& type); + + TypeImpl& + operator = (const TypeImpl& rhs); + + bool + operator == (const TypeImpl& rhs) + { + return m_clang_ast_type == rhs.m_clang_ast_type && m_type_sp.get() == rhs.m_type_sp.get(); + } + + bool + operator != (const TypeImpl& rhs) + { + return m_clang_ast_type != rhs.m_clang_ast_type || m_type_sp.get() != rhs.m_type_sp.get(); + } + + bool + IsValid() + { + return m_type_sp.get() != NULL || m_clang_ast_type.IsValid(); + } + + const lldb_private::ClangASTType & + GetClangASTType() const + { + return m_clang_ast_type; + } + + clang::ASTContext* + GetASTContext(); + + lldb::clang_type_t + GetOpaqueQualType(); + + lldb::TypeSP + GetTypeSP () + { + return m_type_sp; + } + + ConstString + GetName (); + + bool + GetDescription (lldb_private::Stream &strm, + lldb::DescriptionLevel description_level); + + void + SetType (const lldb::TypeSP &type_sp); + +private: + ClangASTType m_clang_ast_type; + lldb::TypeSP m_type_sp; +}; + +class TypeListImpl +{ +public: + TypeListImpl() : + m_content() + { + } + + void + Append (const lldb::TypeImplSP& type) + { + m_content.push_back(type); + } + + class AppendVisitor + { + public: + AppendVisitor(TypeListImpl &type_list) : + m_type_list(type_list) + { + } + + void + operator() (const lldb::TypeImplSP& type) + { + m_type_list.Append(type); + } + + private: + TypeListImpl &m_type_list; + }; + + void + Append (const lldb_private::TypeList &type_list); + + lldb::TypeImplSP + GetTypeAtIndex(size_t idx) + { + lldb::TypeImplSP type_sp; + if (idx < GetSize()) + type_sp = m_content[idx]; + return type_sp; + } + + size_t + GetSize() + { + return m_content.size(); + } + +private: + std::vector<lldb::TypeImplSP> m_content; +}; + +class TypeMemberImpl +{ +public: + TypeMemberImpl () : + m_type_impl_sp (), + m_bit_offset (0), + m_name (), + m_bitfield_bit_size (0), + m_is_bitfield (false) + + { + } + + TypeMemberImpl (const lldb::TypeImplSP &type_impl_sp, + uint64_t bit_offset, + const ConstString &name, + uint32_t bitfield_bit_size = 0, + bool is_bitfield = false) : + m_type_impl_sp (type_impl_sp), + m_bit_offset (bit_offset), + m_name (name), + m_bitfield_bit_size (bitfield_bit_size), + m_is_bitfield (is_bitfield) + { + } + + TypeMemberImpl (const lldb::TypeImplSP &type_impl_sp, + uint64_t bit_offset): + m_type_impl_sp (type_impl_sp), + m_bit_offset (bit_offset), + m_name (), + m_bitfield_bit_size (0), + m_is_bitfield (false) + { + if (m_type_impl_sp) + m_name = m_type_impl_sp->GetName(); + } + + const lldb::TypeImplSP & + GetTypeImpl () + { + return m_type_impl_sp; + } + + const ConstString & + GetName () const + { + return m_name; + } + + uint64_t + GetBitOffset () const + { + return m_bit_offset; + } + + uint32_t + GetBitfieldBitSize () const + { + return m_bitfield_bit_size; + } + + void + SetBitfieldBitSize (uint32_t bitfield_bit_size) + { + m_bitfield_bit_size = bitfield_bit_size; + } + + bool + GetIsBitfield () const + { + return m_is_bitfield; + } + + void + SetIsBitfield (bool is_bitfield) + { + m_is_bitfield = is_bitfield; + } + +protected: + lldb::TypeImplSP m_type_impl_sp; + uint64_t m_bit_offset; + ConstString m_name; + uint32_t m_bitfield_bit_size; // Bit size for bitfield members only + bool m_is_bitfield; +}; + + +} // namespace lldb_private + +#endif // liblldb_Type_h_ + diff --git a/include/lldb/Symbol/TypeList.h b/include/lldb/Symbol/TypeList.h new file mode 100644 index 0000000..9c74db6 --- /dev/null +++ b/include/lldb/Symbol/TypeList.h @@ -0,0 +1,88 @@ +//===-- TypeList.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_TypeList_h_ +#define liblldb_TypeList_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/Type.h" +#include <map> + +namespace lldb_private { + +class TypeList +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + TypeList(); + + virtual + ~TypeList(); + + void + Clear(); + + void + Dump(Stream *s, bool show_context); + +// lldb::TypeSP +// FindType(lldb::user_id_t uid); + + TypeList + FindTypes(const ConstString &name); + + void + Insert (const lldb::TypeSP& type); + + bool + InsertUnique (const lldb::TypeSP& type); + + uint32_t + GetSize() const; + + lldb::TypeSP + GetTypeAtIndex(uint32_t idx); + + void + ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const; + + void + ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback); + + bool + RemoveTypeWithUID (lldb::user_id_t uid); + + void + RemoveMismatchedTypes (const char *qualified_typename, + bool exact_match); + + void + RemoveMismatchedTypes (const std::string &type_scope, + const std::string &type_basename, + lldb::TypeClass type_class, + bool exact_match); + + void + RemoveMismatchedTypes (lldb::TypeClass type_class); + +private: + typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + collection m_types; + + DISALLOW_COPY_AND_ASSIGN (TypeList); +}; + +} // namespace lldb_private + +#endif // liblldb_TypeList_h_ diff --git a/include/lldb/Symbol/TypeVendor.h b/include/lldb/Symbol/TypeVendor.h new file mode 100644 index 0000000..559b21e --- /dev/null +++ b/include/lldb/Symbol/TypeVendor.h @@ -0,0 +1,61 @@ +//===-- TypeVendor.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_TypeVendor_h_ +#define liblldb_TypeVendor_h_ + +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// The type vendor class is intended as a generic interface to search +// for Clang types that are not necessarily backed by a specific symbol +// file. +//---------------------------------------------------------------------- +class TypeVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + TypeVendor() + { + } + + virtual + ~TypeVendor() + { + } + + virtual uint32_t + FindTypes (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector <ClangASTType> &types) = 0; + + virtual clang::ASTContext * + GetClangASTContext () = 0; + +protected: + //------------------------------------------------------------------ + // Classes that inherit from TypeVendor can see and modify these + //------------------------------------------------------------------ + +private: + //------------------------------------------------------------------ + // For TypeVendor only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (TypeVendor); +}; + + +} // namespace lldb_private + +#endif diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h new file mode 100644 index 0000000..6fc5ce0 --- /dev/null +++ b/include/lldb/Symbol/UnwindPlan.h @@ -0,0 +1,499 @@ +#ifndef liblldb_UnwindPlan_h +#define liblldb_UnwindPlan_h + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ConstString.h" + +#include <map> +#include <vector> + +namespace lldb_private { + +// The UnwindPlan object specifies how to unwind out of a function - where +// this function saves the caller's register values before modifying them +// (for non-volatile aka saved registers) and how to find this frame's +// Canonical Frame Address (CFA). + +// Most commonly, registers are saved on the stack, offset some bytes from +// the Canonical Frame Address, or CFA, which is the starting address of +// this function's stack frame (the CFA is same as the eh_frame's CFA, +// whatever that may be on a given architecture). +// The CFA address for the stack frame does not change during +// the lifetime of the function. + +// Internally, the UnwindPlan is structured as a vector of register locations +// organized by code address in the function, showing which registers have been +// saved at that point and where they are saved. +// It can be thought of as the expanded table form of the DWARF CFI +// encoded information. + +// Other unwind information sources will be converted into UnwindPlans before +// being added to a FuncUnwinders object. The unwind source may be +// an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based +// prologue analysis. +// The UnwindPlan is the canonical form of this information that the unwinder +// code will use when walking the stack. + +class UnwindPlan { +public: + + class Row { + public: + class RegisterLocation + { + public: + + enum RestoreType + { + unspecified, // not specified, we may be able to assume this + // is the same register. gcc doesn't specify all + // initial values so we really don't know... + undefined, // reg is not available, e.g. volatile reg + same, // reg is unchanged + atCFAPlusOffset, // reg = deref(CFA + offset) + isCFAPlusOffset, // reg = CFA + offset + inOtherRegister, // reg = other reg + atDWARFExpression, // reg = deref(eval(dwarf_expr)) + isDWARFExpression // reg = eval(dwarf_expr) + }; + + RegisterLocation() : + m_type(unspecified), + m_location() + { + } + + bool + operator == (const RegisterLocation& rhs) const; + + bool + operator != (const RegisterLocation &rhs) const + { + return !(*this == rhs); + } + + void + SetUnspecified() + { + m_type = unspecified; + } + + void + SetUndefined() + { + m_type = undefined; + } + + void + SetSame() + { + m_type = same; + } + + bool + IsSame () const + { + return m_type == same; + } + + bool + IsUnspecified () const + { + return m_type == unspecified; + } + + bool + IsCFAPlusOffset () const + { + return m_type == isCFAPlusOffset; + } + + bool + IsAtCFAPlusOffset () const + { + return m_type == atCFAPlusOffset; + } + + bool + IsInOtherRegister () const + { + return m_type == inOtherRegister; + } + + bool + IsAtDWARFExpression () const + { + return m_type == atDWARFExpression; + } + + bool + IsDWARFExpression () const + { + return m_type == isDWARFExpression; + } + + void + SetAtCFAPlusOffset (int32_t offset) + { + m_type = atCFAPlusOffset; + m_location.offset = offset; + } + + void + SetIsCFAPlusOffset (int32_t offset) + { + m_type = isCFAPlusOffset; + m_location.offset = offset; + } + + void + SetInRegister (uint32_t reg_num) + { + m_type = inOtherRegister; + m_location.reg_num = reg_num; + } + + uint32_t + GetRegisterNumber () const + { + if (m_type == inOtherRegister) + return m_location.reg_num; + return LLDB_INVALID_REGNUM; + } + + RestoreType + GetLocationType () const + { + return m_type; + } + + int32_t + GetOffset () const + { + if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset) + return m_location.offset; + return 0; + } + + void + GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const + { + if (m_type == atDWARFExpression || m_type == isDWARFExpression) + { + *opcodes = m_location.expr.opcodes; + len = m_location.expr.length; + } + else + { + *opcodes = NULL; + len = 0; + } + } + + void + SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len); + + void + SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len); + + const uint8_t * + GetDWARFExpressionBytes () + { + if (m_type == atDWARFExpression || m_type == isDWARFExpression) + return m_location.expr.opcodes; + return NULL; + } + + int + GetDWARFExpressionLength () + { + if (m_type == atDWARFExpression || m_type == isDWARFExpression) + return m_location.expr.length; + return 0; + } + + void + Dump (Stream &s, + const UnwindPlan* unwind_plan, + const UnwindPlan::Row* row, + Thread* thread, + bool verbose) const; + + private: + RestoreType m_type; // How do we locate this register? + union + { + // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset + int32_t offset; + // For m_type == inOtherRegister + uint32_t reg_num; // The register number + // For m_type == atDWARFExpression or m_type == isDWARFExpression + struct { + const uint8_t *opcodes; + uint16_t length; + } expr; + } m_location; + }; + + public: + Row (); + + Row (const UnwindPlan::Row& rhs) : + m_offset (rhs.m_offset), + m_cfa_reg_num (rhs.m_cfa_reg_num), + m_cfa_offset (rhs.m_cfa_offset), + m_register_locations (rhs.m_register_locations) + { + } + + bool + operator == (const Row &rhs) const; + + bool + GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const; + + void + SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location); + + lldb::addr_t + GetOffset() const + { + return m_offset; + } + + void + SetOffset(lldb::addr_t offset) + { + m_offset = offset; + } + + void + SlideOffset(lldb::addr_t offset) + { + m_offset += offset; + } + + uint32_t + GetCFARegister () const + { + return m_cfa_reg_num; + } + + bool + SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, + int32_t offset, + bool can_replace); + + bool + SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, + int32_t offset, + bool can_replace); + + bool + SetRegisterLocationToUndefined (uint32_t reg_num, + bool can_replace, + bool can_replace_only_if_unspecified); + + bool + SetRegisterLocationToUnspecified (uint32_t reg_num, + bool can_replace); + + bool + SetRegisterLocationToRegister (uint32_t reg_num, + uint32_t other_reg_num, + bool can_replace); + + bool + SetRegisterLocationToSame (uint32_t reg_num, + bool must_replace); + + + + void + SetCFARegister (uint32_t reg_num); + + int32_t + GetCFAOffset () const + { + return m_cfa_offset; + } + + void + SetCFAOffset (int32_t offset) + { + m_cfa_offset = offset; + } + + void + Clear (); + + void + Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, lldb::addr_t base_addr) const; + + protected: + typedef std::map<uint32_t, RegisterLocation> collection; + lldb::addr_t m_offset; // Offset into the function for this row + uint32_t m_cfa_reg_num; // The Call Frame Address register number + int32_t m_cfa_offset; // The offset from the CFA for this row + collection m_register_locations; + }; // class Row + +public: + + typedef std::shared_ptr<Row> RowSP; + + UnwindPlan (lldb::RegisterKind reg_kind) : + m_row_list (), + m_plan_valid_address_range (), + m_register_kind (reg_kind), + m_return_addr_register (LLDB_INVALID_REGNUM), + m_source_name (), + m_plan_is_sourced_from_compiler (eLazyBoolCalculate), + m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate) + { + } + + ~UnwindPlan () + { + } + + void + Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const; + + void + AppendRow (const RowSP& row_sp); + + // Returns a pointer to the best row for the given offset into the function's instructions. + // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned. + // In practice, the UnwindPlan for a function with no known start address will be the architectural default + // UnwindPlan which will only have one row. + UnwindPlan::RowSP + GetRowForFunctionOffset (int offset) const; + + lldb::RegisterKind + GetRegisterKind () const + { + return m_register_kind; + } + + void + SetRegisterKind (lldb::RegisterKind kind) + { + m_register_kind = kind; + } + + void + SetReturnAddressRegister (uint32_t regnum) + { + m_return_addr_register = regnum; + } + + uint32_t + GetReturnAddressRegister (void) + { + return m_return_addr_register; + } + + uint32_t + GetInitialCFARegister () const + { + if (m_row_list.empty()) + return LLDB_INVALID_REGNUM; + return m_row_list.front()->GetCFARegister(); + } + + // This UnwindPlan may not be valid at every address of the function span. + // For instance, a FastUnwindPlan will not be valid at the prologue setup + // instructions - only in the body of the function. + void + SetPlanValidAddressRange (const AddressRange& range); + + const AddressRange & + GetAddressRange () const + { + return m_plan_valid_address_range; + } + + bool + PlanValidAtAddress (Address addr); + + bool + IsValidRowIndex (uint32_t idx) const; + + const UnwindPlan::RowSP + GetRowAtIndex (uint32_t idx) const; + + const UnwindPlan::RowSP + GetLastRow () const; + + lldb_private::ConstString + GetSourceName () const; + + void + SetSourceName (const char *); + + // Was this UnwindPlan emitted by a compiler? + lldb_private::LazyBool + GetSourcedFromCompiler () const + { + return m_plan_is_sourced_from_compiler; + } + + // Was this UnwindPlan emitted by a compiler? + void + SetSourcedFromCompiler (lldb_private::LazyBool from_compiler) + { + m_plan_is_sourced_from_compiler = from_compiler; + } + + // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites, + // e.g. for exception handling. + lldb_private::LazyBool + GetUnwindPlanValidAtAllInstructions () const + { + return m_plan_is_valid_at_all_instruction_locations; + } + + // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites, + // e.g. for exception handling. + void + SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn) + { + m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn; + } + + int + GetRowCount () const; + + void + Clear() + { + m_row_list.clear(); + m_plan_valid_address_range.Clear(); + m_register_kind = lldb::eRegisterKindDWARF; + m_source_name.Clear(); + } + + const RegisterInfo * + GetRegisterInfo (Thread* thread, uint32_t reg_num) const; + +private: + + + typedef std::vector<RowSP> collection; + collection m_row_list; + AddressRange m_plan_valid_address_range; + lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers are in terms of - will need to be + // translated to lldb native reg nums at unwind time + uint32_t m_return_addr_register; // The register that has the return address for the caller frame + // e.g. the lr on arm + lldb_private::ConstString m_source_name; // for logging, where this UnwindPlan originated from + lldb_private::LazyBool m_plan_is_sourced_from_compiler; + lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations; +}; // class UnwindPlan + +} // namespace lldb_private + +#endif //liblldb_UnwindPlan_h diff --git a/include/lldb/Symbol/UnwindTable.h b/include/lldb/Symbol/UnwindTable.h new file mode 100644 index 0000000..cefb91e --- /dev/null +++ b/include/lldb/Symbol/UnwindTable.h @@ -0,0 +1,69 @@ +//===-- Symtab.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_UnwindTable_h +#define liblldb_UnwindTable_h + +#include <map> + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// A class which holds all the FuncUnwinders objects for a given ObjectFile. +// The UnwindTable is populated with FuncUnwinders objects lazily during +// the debug session. + +class UnwindTable +{ +public: + UnwindTable(ObjectFile& objfile); + ~UnwindTable(); + + lldb_private::DWARFCallFrameInfo * + GetEHFrameInfo (); + + lldb::FuncUnwindersSP + GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc); + +// Normally when we create a new FuncUnwinders object we track it in this UnwindTable so it can +// be reused later. But for the target modules show-unwind we want to create brand new +// UnwindPlans for the function of interest - so ignore any existing FuncUnwinders for that +// function and don't add this new one to our UnwindTable. +// This FuncUnwinders object does have a reference to the UnwindTable but the lifetime of this +// uncached FuncUnwinders is expected to be short so in practice this will not be a problem. + lldb::FuncUnwindersSP + GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc); + +private: + void + Dump (Stream &s); + + void Initialize (); + + typedef std::map<lldb::addr_t, lldb::FuncUnwindersSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + ObjectFile& m_object_file; + collection m_unwinds; + + bool m_initialized; // delay some initialization until ObjectFile is set up + + UnwindAssembly* m_assembly_profiler; + + DWARFCallFrameInfo* m_eh_frame; + + DISALLOW_COPY_AND_ASSIGN (UnwindTable); +}; + +} // namespace lldb_private + +#endif // liblldb_UnwindTable_h diff --git a/include/lldb/Symbol/Variable.h b/include/lldb/Symbol/Variable.h new file mode 100644 index 0000000..07295d0 --- /dev/null +++ b/include/lldb/Symbol/Variable.h @@ -0,0 +1,184 @@ +//===-- Variable.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_Variable_h_ +#define liblldb_Variable_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Core/UserID.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/Declaration.h" + +namespace lldb_private { + +class Variable : public UserID +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Variable (lldb::user_id_t uid, + const char *name, + const char *mangled, // The mangled variable name for variables in namespaces + const lldb::SymbolFileTypeSP &symfile_type_sp, + lldb::ValueType scope, + SymbolContextScope *owner_scope, + Declaration* decl, + const DWARFExpression& location, + bool external, + bool artificial); + + virtual + ~Variable(); + + void + Dump(Stream *s, bool show_context) const; + + bool + DumpDeclaration (Stream *s, + bool show_fullpaths, + bool show_module); + + const Declaration& + GetDeclaration() const + { + return m_declaration; + } + + 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 + // function that can be called by commands and expression parsers to make + // sure we match anything we come across. + bool + NameMatches (const ConstString &name) const + { + if (m_name == name) + return true; + return m_mangled.NameMatches (name); + } + + bool + NameMatches (const RegularExpression& regex) const; + + Type * + GetType(); + + lldb::ValueType + GetScope() const + { + return m_scope; + } + + bool + IsExternal() const + { + return m_external; + } + + bool + IsArtificial() const + { + return m_artificial; + } + + DWARFExpression & + LocationExpression() + { + return m_location; + } + + const DWARFExpression & + LocationExpression() const + { + return m_location; + } + + bool + DumpLocationForAddress (Stream *s, + const Address &address); + + size_t + MemorySize() const; + + void + CalculateSymbolContext (SymbolContext *sc); + + bool + IsInScope (StackFrame *frame); + + bool + LocationIsValidForFrame (StackFrame *frame); + + bool + LocationIsValidForAddress (const Address &address); + + bool + GetLocationIsConstantValueData () const + { + return m_loc_is_const_data; + } + + void + SetLocationIsConstantValueData (bool b) + { + m_loc_is_const_data = b; + } + + typedef size_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); + + static size_t + AutoComplete (const ExecutionContext &exe_ctx, + const char *name, + StringList &matches, + bool &word_complete); + +protected: + ConstString m_name; // The basename of the variable (no namespaces) + Mangled m_mangled; // The mangled name of the variable + lldb::SymbolFileTypeSP m_symfile_type_sp; // The type pointer of the variable (int, struct, class, etc) + lldb::ValueType m_scope; // global, parameter, local + SymbolContextScope *m_owner_scope; // The symbol file scope that this variable was defined in + Declaration m_declaration; // Declaration location for this item. + DWARFExpression m_location; // The location of this variable that can be fed to DWARFExpression::Evaluate() + uint8_t m_external:1, // Visible outside the containing compile unit? + m_artificial:1, // Non-zero if the variable is not explicitly declared in source + m_loc_is_const_data:1; // The m_location expression contains the constant variable value data, not a DWARF location +private: + Variable(const Variable& rhs); + Variable& operator=(const Variable& rhs); +}; + +} // namespace lldb_private + +#endif // liblldb_Variable_h_ diff --git a/include/lldb/Symbol/VariableList.h b/include/lldb/Symbol/VariableList.h new file mode 100644 index 0000000..2ce6146 --- /dev/null +++ b/include/lldb/Symbol/VariableList.h @@ -0,0 +1,95 @@ +//===-- VariableList.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_VariableList_h_ +#define liblldb_VariableList_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Variable.h" + +namespace lldb_private { + +class VariableList +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ +// VariableList(const SymbolContext &symbol_context); + VariableList(); + virtual ~VariableList(); + + void + AddVariable (const lldb::VariableSP &var_sp); + + bool + AddVariableIfUnique (const lldb::VariableSP &var_sp); + + void + AddVariables (VariableList *variable_list); + + void + Clear(); + + void + Dump(Stream *s, bool show_context) const; + + lldb::VariableSP + GetVariableAtIndex(size_t idx) const; + + lldb::VariableSP + RemoveVariableAtIndex (size_t idx); + + lldb::VariableSP + FindVariable (const ConstString& name); + + uint32_t + FindVariableIndex (const lldb::VariableSP &var_sp); + + // Returns the actual number of unique variables that were added to the + // list. "total_matches" will get updated with the actualy number of + // matches that were found regardless of whether they were unique or not + // to allow for error conditions when nothing is found, versus conditions + // where any varaibles that match "regex" were already in "var_list". + size_t + AppendVariablesIfUnique (const RegularExpression& regex, + VariableList &var_list, + size_t& total_matches); + + size_t + AppendVariablesWithScope (lldb::ValueType type, + VariableList &var_list, + bool if_unique = true); + + uint32_t + FindIndexForVariable (Variable* variable); + + size_t + MemorySize() const; + + size_t + GetSize() const; + +protected: + typedef std::vector<lldb::VariableSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + collection m_variables; +private: + //------------------------------------------------------------------ + // For VariableList only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (VariableList); +}; + +} // namespace lldb_private + +#endif // liblldb_VariableList_h_ diff --git a/include/lldb/Symbol/VerifyDecl.h b/include/lldb/Symbol/VerifyDecl.h new file mode 100644 index 0000000..228e635 --- /dev/null +++ b/include/lldb/Symbol/VerifyDecl.h @@ -0,0 +1,20 @@ +//===-- VerifyDecl.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_VariableList_h_ +#define lldb_VariableList_h_ + +#include "lldb/Core/ClangForward.h" + +namespace lldb_private +{ + void VerifyDecl (clang::Decl *decl); +} + +#endif diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h new file mode 100644 index 0000000..16f8ee7 --- /dev/null +++ b/include/lldb/Target/ABI.h @@ -0,0 +1,137 @@ +//===-- ABI.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_ABI_h_ +#define liblldb_ABI_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Error.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class ABI : + public PluginInterface +{ +public: + virtual + ~ABI(); + + virtual size_t + GetRedZoneSize () const = 0; + + virtual bool + PrepareTrivialCall (Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + lldb::addr_t *arg1_ptr = NULL, + lldb::addr_t *arg2_ptr = NULL, + lldb::addr_t *arg3_ptr = NULL, + lldb::addr_t *arg4_ptr = NULL, + lldb::addr_t *arg5_ptr = NULL, + lldb::addr_t *arg6_ptr = NULL) const = 0; + + virtual bool + GetArgumentValues (Thread &thread, + ValueList &values) const = 0; + + lldb::ValueObjectSP + GetReturnValueObject (Thread &thread, + ClangASTType &type, + bool persistent = true) const; + + // Set the Return value object in the current frame as though a function with + virtual Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) = 0; + +protected: + // This is the method the ABI will call to actually calculate the return value. + // Don't put it in a persistant value object, that will be done by the ABI::GetReturnValueObject. + virtual lldb::ValueObjectSP + GetReturnValueObjectImpl (Thread &thread, + ClangASTType &type) const = 0; +public: + virtual bool + CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) = 0; + + virtual bool + CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) = 0; + + virtual bool + RegisterIsVolatile (const RegisterInfo *reg_info) = 0; + + // Should return true if your ABI uses frames when doing stack backtraces. This + // means a frame pointer is used that points to the previous stack frame in some + // way or another. + virtual bool + StackUsesFrames () = 0; + + // Should take a look at a call frame address (CFA) which is just the stack + // pointer value upon entry to a function. ABIs usually impose alignment + // restrictions (4, 8 or 16 byte aligned), and zero is usually not allowed. + // This function should return true if "cfa" is valid call frame address for + // the ABI, and false otherwise. This is used by the generic stack frame unwinding + // code to help determine when a stack ends. + virtual bool + CallFrameAddressIsValid (lldb::addr_t cfa) = 0; + + // Validates a possible PC value and returns true if an opcode can be at "pc". + virtual bool + CodeAddressIsValid (lldb::addr_t pc) = 0; + + virtual lldb::addr_t + FixCodeAddress (lldb::addr_t pc) + { + // Some targets might use bits in a code address to indicate + // a mode switch. ARM uses bit zero to signify a code address is + // thumb, so any ARM ABI plug-ins would strip those bits. + return pc; + } + + virtual const RegisterInfo * + GetRegisterInfoArray (uint32_t &count) = 0; + + // Some architectures (e.g. x86) will push the return address on the stack and decrement + // the stack pointer when making a function call. This means that every stack frame will + // have a unique CFA. + // Other architectures (e.g. arm) pass the return address in a register so it is possible + // to have a frame on a backtrace that does not push anything on the stack or change the + // CFA. + virtual bool + FunctionCallsChangeCFA () = 0; + + + bool + GetRegisterInfoByName (const ConstString &name, RegisterInfo &info); + + bool + GetRegisterInfoByKind (lldb::RegisterKind reg_kind, + uint32_t reg_num, + RegisterInfo &info); + + static lldb::ABISP + FindPlugin (const ArchSpec &arch); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from ABI can see and modify these + //------------------------------------------------------------------ + ABI(); +private: + DISALLOW_COPY_AND_ASSIGN (ABI); +}; + +} // namespace lldb_private + +#endif // liblldb_ABI_h_ diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h new file mode 100644 index 0000000..98a4ab8 --- /dev/null +++ b/include/lldb/Target/CPPLanguageRuntime.h @@ -0,0 +1,158 @@ +//===-- CPPLanguageRuntime.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_CPPLanguageRuntime_h_ +#define liblldb_CPPLanguageRuntime_h_ + +// C Includes +// C++ Includes +#include <vector> +// Other libraries and framework includes +// Project includes +#include "lldb/Core/PluginInterface.h" +#include "lldb/lldb-private.h" +#include "lldb/Target/LanguageRuntime.h" + +namespace lldb_private { + +class CPPLanguageRuntime : + public LanguageRuntime +{ +public: + + class MethodName + { + public: + enum Type + { + eTypeInvalid, + eTypeUnknownMethod, + eTypeClassMethod, + eTypeInstanceMethod + }; + + MethodName () : + m_full(), + m_basename(), + m_context(), + m_arguments(), + m_qualifiers(), + m_type (eTypeInvalid), + m_parsed (false), + m_parse_error (false) + { + } + + MethodName (const ConstString &s) : + m_full(s), + m_basename(), + m_context(), + m_arguments(), + m_qualifiers(), + m_type (eTypeInvalid), + m_parsed (false), + m_parse_error (false) + { + } + + void + Clear(); + + bool + IsValid () const + { + if (m_parse_error) + return false; + if (m_type == eTypeInvalid) + return false; + return (bool)m_full; + } + + Type + GetType () const + { + return m_type; + } + + const ConstString & + GetFullName () const + { + return m_full; + } + + llvm::StringRef + GetBasename (); + + llvm::StringRef + GetContext (); + + llvm::StringRef + GetArguments (); + + llvm::StringRef + GetQualifiers (); + + protected: + void + Parse(); + + ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const" + llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex" + llvm::StringRef m_context; // Decl context: "lldb::SBTarget" + llvm::StringRef m_arguments; // Arguments: "(unsigned int)" + llvm::StringRef m_qualifiers; // Qualifiers: "const" + Type m_type; + bool m_parsed; + bool m_parse_error; + }; + + virtual + ~CPPLanguageRuntime(); + + virtual lldb::LanguageType + GetLanguageType () const + { + return lldb::eLanguageTypeC_plus_plus; + } + + virtual bool + IsVTableName (const char *name) = 0; + + virtual bool + GetObjectDescription (Stream &str, ValueObject &object); + + virtual bool + GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope); + + static bool + IsCPPMangledName(const char *name); + + static bool + StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end); + + // in some cases, compilers will output different names for one same type. when tht happens, it might be impossible + // to construct SBType objects for a valid type, because the name that is available is not the same as the name that + // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names + // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended + // to ObjC or other languages if necessary + static uint32_t + FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from CPPLanguageRuntime can see and modify these + //------------------------------------------------------------------ + CPPLanguageRuntime(Process *process); +private: + DISALLOW_COPY_AND_ASSIGN (CPPLanguageRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_CPPLanguageRuntime_h_ diff --git a/include/lldb/Target/DynamicLoader.h b/include/lldb/Target/DynamicLoader.h new file mode 100644 index 0000000..6b76e58 --- /dev/null +++ b/include/lldb/Target/DynamicLoader.h @@ -0,0 +1,239 @@ +//===-- DynamicLoader.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_DynamicLoader_h_ +#define liblldb_DynamicLoader_h_ + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/PluginInterface.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class DynamicLoader DynamicLoader.h "lldb/Target/DynamicLoader.h" +/// @brief A plug-in interface definition class for dynamic loaders. +/// +/// Dynamic loader plug-ins track image (shared library) loading and +/// unloading. The class is initialized given a live process that is +/// halted at its entry point or just after attaching. +/// +/// Dynamic loader plug-ins can track the process by registering +/// callbacks using the: +/// Process::RegisterNotificationCallbacks (const Notifications&) +/// function. +/// +/// Breakpoints can also be set in the process which can register +/// functions that get called using: +/// Process::BreakpointSetCallback (lldb::user_id_t, BreakpointHitCallback, void *). +/// These breakpoint callbacks return a boolean value that indicates if +/// the process should continue or halt and should return the global +/// setting for this using: +/// DynamicLoader::StopWhenImagesChange() const. +//---------------------------------------------------------------------- +class DynamicLoader : + public PluginInterface +{ +public: + //------------------------------------------------------------------ + /// Find a dynamic loader plugin for a given process. + /// + /// Scans the installed DynamicLoader plug-ins and tries to find + /// an instance that can be used to track image changes in \a + /// process. + /// + /// @param[in] process + /// The process for which to try and locate a dynamic loader + /// plug-in instance. + /// + /// @param[in] plugin_name + /// An optional name of a specific dynamic loader plug-in that + /// should be used. If NULL, pick the best plug-in. + //------------------------------------------------------------------ + static DynamicLoader* + FindPlugin (Process *process, const char *plugin_name); + + //------------------------------------------------------------------ + /// Construct with a process. + //------------------------------------------------------------------ + DynamicLoader (Process *process); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~DynamicLoader (); + + //------------------------------------------------------------------ + /// Called after attaching a process. + /// + /// Allow DynamicLoader plug-ins to execute some code after + /// attaching to a process. + //------------------------------------------------------------------ + virtual void + DidAttach () = 0; + + //------------------------------------------------------------------ + /// Called after launching a process. + /// + /// Allow DynamicLoader plug-ins to execute some code after + /// the process has stopped for the first time on launch. + //------------------------------------------------------------------ + virtual void + DidLaunch () = 0; + + + //------------------------------------------------------------------ + /// Helper function that can be used to detect when a process has + /// called exec and is now a new and different process. This can + /// be called when necessary to try and detect the exec. The process + /// might be able to answer this question, but sometimes it might + /// not be able and the dynamic loader often knows what the program + /// entry point is. So the process and the dynamic loader can work + /// together to detect this. + //------------------------------------------------------------------ + virtual bool + ProcessDidExec () + { + return false; + } + //------------------------------------------------------------------ + /// Get whether the process should stop when images change. + /// + /// When images (executables and shared libraries) get loaded or + /// unloaded, often debug sessions will want to try and resolve or + /// unresolve breakpoints that are set in these images. Any + /// breakpoints set by DynamicLoader plug-in instances should + /// return this value to ensure consistent debug session behaviour. + /// + /// @return + /// Returns \b true if the process should stop when images + /// change, \b false if the process should resume. + //------------------------------------------------------------------ + bool + GetStopWhenImagesChange () const; + + //------------------------------------------------------------------ + /// Set whether the process should stop when images change. + /// + /// When images (executables and shared libraries) get loaded or + /// unloaded, often debug sessions will want to try and resolve or + /// unresolve breakpoints that are set in these images. The default + /// is set so that the process stops when images change, but this + /// can be overridden using this function callback. + /// + /// @param[in] stop + /// Boolean value that indicates whether the process should stop + /// when images change. + //------------------------------------------------------------------ + void + SetStopWhenImagesChange (bool stop); + + //------------------------------------------------------------------ + /// Provides a plan to step through the dynamic loader trampoline + /// for the current state of \a thread. + /// + /// + /// @param[in] stop_others + /// Whether the plan should be set to stop other threads. + /// + /// @return + /// A pointer to the plan (caller owned) or NULL if we are not at such + /// a trampoline. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0; + + + //------------------------------------------------------------------ + /// Some dynamic loaders provide features where there are a group of symbols "equivalent to" + /// a given symbol one of which will be chosen when the symbol is bound. If you want to + /// set a breakpoint on one of these symbols, you really need to set it on all the + /// equivalent symbols. + /// + /// + /// @param[in] original_symbol + /// The symbol for which we are finding equivalences. + /// + /// @param[in] module_list + /// The set of modules in which to search. + /// + /// @param[out] equivalent_symbols + /// The equivalent symbol list - any equivalent symbols found are appended to this list. + /// + /// @return + /// Number of equivalent symbols found. + //------------------------------------------------------------------ + virtual size_t + FindEquivalentSymbols (Symbol *original_symbol, ModuleList &module_list, SymbolContextList &equivalent_symbols) + { + return 0; + } + + //------------------------------------------------------------------ + /// Ask if it is ok to try and load or unload an shared library + /// (image). + /// + /// The dynamic loader often knows when it would be ok to try and + /// load or unload a shared library. This function call allows the + /// dynamic loader plug-ins to check any current dyld state to make + /// sure it is an ok time to load a shared library. + /// + /// @return + /// \b true if it is currently ok to try and load a shared + /// library into the process, \b false otherwise. + //------------------------------------------------------------------ + virtual Error + CanLoadImage () = 0; + + //------------------------------------------------------------------ + /// Ask if the eh_frame information for the given SymbolContext should + /// be relied on even when it's the first frame in a stack unwind. + /// + /// The CFI instructions from the eh_frame section are normally only + /// valid at call sites -- places where a program could throw an + /// exception and need to unwind out. But some Modules may be known + /// to the system as having reliable eh_frame information at all call + /// sites. This would be the case if the Module's contents are largely + /// hand-written assembly with hand-written eh_frame information. + /// Normally when unwinding from a function at the beginning of a stack + /// unwind lldb will examine the assembly instructions to understand + /// how the stack frame is set up and where saved registers are stored. + /// But with hand-written assembly this is not reliable enough -- we need + /// to consult those function's hand-written eh_frame information. + /// + /// @return + /// \b True if the symbol context should use eh_frame instructions + /// unconditionally when unwinding from this frame. Else \b false, + /// the normal lldb unwind behavior of only using eh_frame when the + /// function appears in the middle of the stack. + //------------------------------------------------------------------ + virtual bool + AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx) + { + return false; + } + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + Process* m_process; ///< The process that this dynamic loader plug-in is tracking. +private: + DISALLOW_COPY_AND_ASSIGN (DynamicLoader); + +}; + +} // namespace lldb_private + +#endif // liblldb_DynamicLoader_h_ diff --git a/include/lldb/Target/ExecutionContext.h b/include/lldb/Target/ExecutionContext.h new file mode 100644 index 0000000..de5fe14 --- /dev/null +++ b/include/lldb/Target/ExecutionContext.h @@ -0,0 +1,778 @@ +//===-- ExecutionContext.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// Execution context objects refer to objects in the execution of the +/// program that is being debugged. The consist of one or more of the +/// following objects: target, process, thread, and frame. Many objects +/// in the debugger need to track different executions contexts. For +/// example, a local function variable might have an execution context +/// that refers to a stack frame. A global or static variable might +/// refer to a target since a stack frame isn't required in order to +/// evaluate a global or static variable (a process isn't necessarily +/// needed for a global variable since we might be able to read the +/// variable value from a data section in one of the object files in +/// a target). There are two types of objects that hold onto execution +/// contexts: ExecutionContextRef and ExecutionContext. Both of these +/// objects are deascribed below. +/// +/// Not all objects in an ExectionContext objects will be valid. If you want +/// to refer stronly (ExectionContext) or weakly (ExectionContextRef) to +/// a process, then only the process and target references will be valid. +/// For threads, only the thread, process and target references will be +/// filled in. For frames, all of the objects will be filled in. +/// +/// These classes are designed to be used as baton objects that get passed +/// to a wide variety of functions that require execution contexts. +//===----------------------------------------------------------------------===// + + + +#ifndef liblldb_ExecutionContext_h_ +#define liblldb_ExecutionContext_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Target/StackID.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ExecutionContextRef ExecutionContext.h "lldb/Target/ExecutionContext.h" +/// @brief A class that holds a weak reference to an execution context. +/// +/// ExecutionContextRef objects are designed to hold onto an execution +/// context that might change over time. For example, if an object wants +/// to refer to a stack frame, it should hold onto an ExecutionContextRef +/// to a frame object. The backing object that represents the stack frame +/// might change over time and instaces of this object can track the logical +/// object that refers to a frame even if it does change. +/// +/// These objects also don't keep execution objects around longer than they +/// should since they use weak pointers. For example if an object refers +/// to a stack frame and a stack frame is no longer in a thread, then a +/// ExecutionContextRef object that refers to that frame will not be able +/// to get a shared pointer to those objects since they are no longer around. +/// +/// ExecutionContextRef objects can also be used as objects in classes +/// that want to track a "previous execution context". Since the weak +/// references to the execution objects (target, process, thread and frame) +/// don't keep these objects around, they are safe to keep around. +/// +/// The general rule of thumb is all long lived objects that want to +/// refer to execution contexts should use ExecutionContextRef objcts. +/// The ExecutionContext class is used to temporarily get shared +/// pointers to any execution context objects that are still around +/// so they are guaranteed to exist during a function that requires the +/// objects. ExecutionContext objects should NOT be used for long term +/// storage since they will keep objects alive with extra shared pointer +/// references to these objects. +//---------------------------------------------------------------------- +class ExecutionContextRef +{ +public: + //------------------------------------------------------------------ + /// Default Constructor. + //------------------------------------------------------------------ + ExecutionContextRef(); + + //------------------------------------------------------------------ + /// Copy Constructor. + //------------------------------------------------------------------ + ExecutionContextRef (const ExecutionContextRef &rhs); + + //------------------------------------------------------------------ + /// Construct using an ExecutionContext object that might be NULL. + /// + /// If \a exe_ctx_ptr is valid, then make weak references to any + /// valid objects in the ExecutionContext, othewise no weak + /// references to any execution context objects will be made. + //------------------------------------------------------------------ + ExecutionContextRef (const ExecutionContext *exe_ctx_ptr); + + //------------------------------------------------------------------ + /// Construct using an ExecutionContext object. + /// + /// Make weak references to any valid objects in the ExecutionContext. + //------------------------------------------------------------------ + ExecutionContextRef (const ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Assignment operator + /// + /// Copy all weak refernces in \a rhs. + //------------------------------------------------------------------ + ExecutionContextRef & + operator =(const ExecutionContextRef &rhs); + + //------------------------------------------------------------------ + /// Assignment operator from a ExecutionContext + /// + /// Make weak refernces to any stringly referenced objects in \a exe_ctx. + //------------------------------------------------------------------ + ExecutionContextRef & + operator =(const ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Construct using the target and all the selected items inside of it + /// (the process and its selected thread, and the thread's selected + /// frame). If there is no selected thread, default to the first thread + /// If there is no selected frame, default to the first frame. + //------------------------------------------------------------------ + ExecutionContextRef (Target *target, bool adopt_selected); + + //------------------------------------------------------------------ + /// Construct using an execution context scope. + /// + /// If the ExecutionContextScope object is valid and refers to a frame, + /// make weak refernces too the frame, thread, process and target. + /// If the ExecutionContextScope object is valid and refers to a thread, + /// make weak refernces too the thread, process and target. + /// If the ExecutionContextScope object is valid and refers to a process, + /// make weak refernces too the process and target. + /// If the ExecutionContextScope object is valid and refers to a target, + /// make weak refernces too the target. + //------------------------------------------------------------------ + ExecutionContextRef (ExecutionContextScope *exe_scope); + + //------------------------------------------------------------------ + /// Construct using an execution context scope. + /// + /// If the ExecutionContextScope object refers to a frame, + /// make weak refernces too the frame, thread, process and target. + /// If the ExecutionContextScope object refers to a thread, + /// make weak refernces too the thread, process and target. + /// If the ExecutionContextScope object refers to a process, + /// make weak refernces too the process and target. + /// If the ExecutionContextScope object refers to a target, + /// make weak refernces too the target. + //------------------------------------------------------------------ + ExecutionContextRef (ExecutionContextScope &exe_scope); + + ~ExecutionContextRef(); + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the process and thread to NULL, and the frame index to an + /// invalid value. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Set accessor that creates a weak reference to the target + /// referenced in \a target_sp. + /// + /// If \a target_sp is valid this object will create a weak + /// reference to that object, otherwise any previous target weak + /// reference contained in this object will be reset. + /// + /// Only the weak reference to the target will be updated, no other + /// weak references will be modified. If you want this execution + /// context to make a weak reference to the target's process, use + /// the ExecutionContextRef::SetContext() functions. + /// + /// @see ExecutionContextRef::SetContext(const lldb::TargetSP &, bool) + //------------------------------------------------------------------ + void + SetTargetSP (const lldb::TargetSP &target_sp); + + //------------------------------------------------------------------ + /// Set accessor that creates a weak reference to the process + /// referenced in \a process_sp. + /// + /// If \a process_sp is valid this object will create a weak + /// reference to that object, otherwise any previous process weak + /// reference contained in this object will be reset. + /// + /// Only the weak reference to the process will be updated, no other + /// weak references will be modified. If you want this execution + /// context to make a weak reference to the target, use the + /// ExecutionContextRef::SetContext() functions. + /// + /// @see ExecutionContextRef::SetContext(const lldb::ProcessSP &) + //------------------------------------------------------------------ + void + SetProcessSP (const lldb::ProcessSP &process_sp); + + //------------------------------------------------------------------ + /// Set accessor that creates a weak reference to the thread + /// referenced in \a thread_sp. + /// + /// If \a thread_sp is valid this object will create a weak + /// reference to that object, otherwise any previous thread weak + /// reference contained in this object will be reset. + /// + /// Only the weak reference to the thread will be updated, no other + /// weak references will be modified. If you want this execution + /// context to make a weak reference to the thread's process and + /// target, use the ExecutionContextRef::SetContext() functions. + /// + /// @see ExecutionContextRef::SetContext(const lldb::ThreadSP &) + //------------------------------------------------------------------ + void + SetThreadSP (const lldb::ThreadSP &thread_sp); + + //------------------------------------------------------------------ + /// Set accessor that creates a weak reference to the frame + /// referenced in \a frame_sp. + /// + /// If \a frame_sp is valid this object will create a weak + /// reference to that object, otherwise any previous frame weak + /// reference contained in this object will be reset. + /// + /// Only the weak reference to the frame will be updated, no other + /// weak references will be modified. If you want this execution + /// context to make a weak reference to the frame's thread, process + /// and target, use the ExecutionContextRef::SetContext() functions. + /// + /// @see ExecutionContextRef::SetContext(const lldb::StackFrameSP &) + //------------------------------------------------------------------ + void + SetFrameSP (const lldb::StackFrameSP &frame_sp); + + void + SetTargetPtr (Target* target, bool adopt_selected); + + void + SetProcessPtr (Process *process); + + void + SetThreadPtr (Thread *thread); + + void + SetFramePtr (StackFrame *frame); + + //------------------------------------------------------------------ + /// Get accessor that creates a strong reference from the weak target + /// reference contained in this object. + /// + /// @returns + /// A shared pointer to a target that is not guaranteed to be valid. + //------------------------------------------------------------------ + lldb::TargetSP + GetTargetSP () const; + + //------------------------------------------------------------------ + /// Get accessor that creates a strong reference from the weak process + /// reference contained in this object. + /// + /// @returns + /// A shared pointer to a process that is not guaranteed to be valid. + //------------------------------------------------------------------ + lldb::ProcessSP + GetProcessSP () const; + + //------------------------------------------------------------------ + /// Get accessor that creates a strong reference from the weak thread + /// reference contained in this object. + /// + /// @returns + /// A shared pointer to a thread that is not guaranteed to be valid. + //------------------------------------------------------------------ + lldb::ThreadSP + GetThreadSP () const; + + //------------------------------------------------------------------ + /// Get accessor that creates a strong reference from the weak frame + /// reference contained in this object. + /// + /// @returns + /// A shared pointer to a frame that is not guaranteed to be valid. + //------------------------------------------------------------------ + lldb::StackFrameSP + GetFrameSP () const; + + //------------------------------------------------------------------ + /// Create an ExecutionContext object from this object. + /// + /// Create strong references to any execution context objects that + /// are still valid. Any of the returned shared pointers in the + /// ExecutionContext objects is not guaranteed to be valid. + /// @returns + /// An execution context object that has strong references to + /// any valid weak references in this object. + //------------------------------------------------------------------ + ExecutionContext + Lock () const; + + //------------------------------------------------------------------ + /// Returns true if this object has a weak reference to a thread. + /// The return value is only an indication of wether this object has + /// a weak reference and does not indicate wether the weak rerference + /// is valid or not. + //------------------------------------------------------------------ + bool + HasThreadRef () const + { + return m_tid != LLDB_INVALID_THREAD_ID; + } + + //------------------------------------------------------------------ + /// Returns true if this object has a weak reference to a frame. + /// The return value is only an indication of wether this object has + /// a weak reference and does not indicate wether the weak rerference + /// is valid or not. + //------------------------------------------------------------------ + bool + HasFrameRef () const + { + return m_stack_id.IsValid(); + } + + void + ClearThread () + { + m_thread_wp.reset(); + m_tid = LLDB_INVALID_THREAD_ID; + } + + void + ClearFrame () + { + m_stack_id.Clear(); + } + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + lldb::TargetWP m_target_wp; ///< A weak reference to a target + lldb::ProcessWP m_process_wp; ///< A weak reference to a process + mutable lldb::ThreadWP m_thread_wp; ///< A weak reference to a thread + lldb::tid_t m_tid; ///< The thread ID that this object refers to in case the backing object changes + StackID m_stack_id; ///< The stack ID that this object refers to in case the backing object changes +}; + +//---------------------------------------------------------------------- +/// @class ExecutionContext ExecutionContext.h "lldb/Target/ExecutionContext.h" +/// @brief A class that contains an execution context. +/// +/// This baton object can be passed into any function that requires +/// a context that specifies a target, process, thread and frame. +/// These objects are designed to be used for short term execution +/// context object storage while a function might be trying to evaluate +/// something that requires a thread or frame. ExecutionContextRef +/// objects can be used to initialize one of these objects to turn +/// the weak execution context object references to the target, process, +/// thread and frame into strong references (shared pointers) so that +/// functions can guarantee that these objects won't go away in the +/// middle of a function. +/// +/// ExecutionContext objects should be used as short lived objects +/// (typically on the stack) in order to lock down an execution context +/// for local use and for passing down to other functions that also +/// require specific contexts. They should NOT be used for long term +/// storage, for long term storage use ExecutionContextRef objects. +//---------------------------------------------------------------------- +class ExecutionContext +{ +public: + //------------------------------------------------------------------ + /// Default Constructor. + //------------------------------------------------------------------ + ExecutionContext(); + + //------------------------------------------------------------------ + // Copy constructor + //------------------------------------------------------------------ + ExecutionContext (const ExecutionContext &rhs); + + //------------------------------------------------------------------ + // Adopt the target and optionally its current context. + //------------------------------------------------------------------ + ExecutionContext (Target* t, bool fill_current_process_thread_frame = true); + + //------------------------------------------------------------------ + // Create execution contexts from shared pointers + //------------------------------------------------------------------ + ExecutionContext (const lldb::TargetSP &target_sp, bool get_process); + ExecutionContext (const lldb::ProcessSP &process_sp); + ExecutionContext (const lldb::ThreadSP &thread_sp); + ExecutionContext (const lldb::StackFrameSP &frame_sp); + //------------------------------------------------------------------ + // Create execution contexts from weak pointers + //------------------------------------------------------------------ + ExecutionContext (const lldb::TargetWP &target_wp, bool get_process); + ExecutionContext (const lldb::ProcessWP &process_wp); + ExecutionContext (const lldb::ThreadWP &thread_wp); + ExecutionContext (const lldb::StackFrameWP &frame_wp); + ExecutionContext (const ExecutionContextRef &exe_ctx_ref); + ExecutionContext (const ExecutionContextRef *exe_ctx_ref); + + // These two variants take in a locker, and grab the target, lock the API mutex into locker, then + // fill in the rest of the shared pointers. + ExecutionContext (const ExecutionContextRef &exe_ctx_ref, Mutex::Locker &locker); + ExecutionContext (const ExecutionContextRef *exe_ctx_ref, Mutex::Locker &locker); + //------------------------------------------------------------------ + // Create execution contexts from execution context scopes + //------------------------------------------------------------------ + ExecutionContext (ExecutionContextScope *exe_scope); + ExecutionContext (ExecutionContextScope &exe_scope); + + + ExecutionContext & + operator =(const ExecutionContext &rhs); + + bool + operator ==(const ExecutionContext &rhs) const; + + bool + operator !=(const ExecutionContext &rhs) const; + + //------------------------------------------------------------------ + /// Construct with process, thread, and frame index. + /// + /// Initialize with process \a p, thread \a t, and frame index \a f. + /// + /// @param[in] process + /// The process for this execution context. + /// + /// @param[in] thread + /// The thread for this execution context. + /// + /// @param[in] frame + /// The frame index for this execution context. + //------------------------------------------------------------------ + ExecutionContext (Process* process, + Thread *thread = NULL, + StackFrame * frame = NULL); + + + ~ExecutionContext(); + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the process and thread to NULL, and the frame index to an + /// invalid value. + //------------------------------------------------------------------ + void + Clear (); + + RegisterContext * + GetRegisterContext () const; + + ExecutionContextScope * + GetBestExecutionContextScope () const; + + uint32_t + GetAddressByteSize() const; + + //------------------------------------------------------------------ + /// Returns a pointer to the target object. + /// + /// The returned pointer might be NULL. Calling HasTargetScope(), + /// HasProcessScope(), HasThreadScope(), or HasFrameScope() + /// can help to pre-validate this pointer so that this accessor can + /// freely be used without having to check for NULL each time. + /// + /// @see ExecutionContext::HasTargetScope() const + /// @see ExecutionContext::HasProcessScope() const + /// @see ExecutionContext::HasThreadScope() const + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + Target * + GetTargetPtr () const; + + //------------------------------------------------------------------ + /// Returns a pointer to the process object. + /// + /// The returned pointer might be NULL. Calling HasProcessScope(), + /// HasThreadScope(), or HasFrameScope() can help to pre-validate + /// this pointer so that this accessor can freely be used without + /// having to check for NULL each time. + /// + /// @see ExecutionContext::HasProcessScope() const + /// @see ExecutionContext::HasThreadScope() const + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + Process * + GetProcessPtr () const; + + //------------------------------------------------------------------ + /// Returns a pointer to the thread object. + /// + /// The returned pointer might be NULL. Calling HasThreadScope() or + /// HasFrameScope() can help to pre-validate this pointer so that + /// this accessor can freely be used without having to check for + /// NULL each time. + /// + /// @see ExecutionContext::HasThreadScope() const + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + Thread * + GetThreadPtr () const + { + return m_thread_sp.get(); + } + + //------------------------------------------------------------------ + /// Returns a pointer to the frame object. + /// + /// The returned pointer might be NULL. Calling HasFrameScope(), + /// can help to pre-validate this pointer so that this accessor can + /// freely be used without having to check for NULL each time. + /// + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + StackFrame * + GetFramePtr () const + { + return m_frame_sp.get(); + } + + //------------------------------------------------------------------ + /// Returns a reference to the target object. + /// + /// Clients should call HasTargetScope(), HasProcessScope(), + /// HasThreadScope(), or HasFrameScope() prior to calling this + /// function to ensure that this ExecutionContext object contains + /// a valid target. + /// + /// @see ExecutionContext::HasTargetScope() const + /// @see ExecutionContext::HasProcessScope() const + /// @see ExecutionContext::HasThreadScope() const + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + Target & + GetTargetRef () const; + + //------------------------------------------------------------------ + /// Returns a reference to the process object. + /// + /// Clients should call HasProcessScope(), HasThreadScope(), or + /// HasFrameScope() prior to calling this function to ensure that + /// this ExecutionContext object contains a valid target. + /// + /// @see ExecutionContext::HasProcessScope() const + /// @see ExecutionContext::HasThreadScope() const + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + Process & + GetProcessRef () const; + + //------------------------------------------------------------------ + /// Returns a reference to the thread object. + /// + /// Clients should call HasThreadScope(), or HasFrameScope() prior + /// to calling this function to ensure that this ExecutionContext + /// object contains a valid target. + /// + /// @see ExecutionContext::HasThreadScope() const + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + Thread & + GetThreadRef () const; + + //------------------------------------------------------------------ + /// Returns a reference to the thread object. + /// + /// Clients should call HasFrameScope() prior to calling this + /// function to ensure that this ExecutionContext object contains + /// a valid target. + /// + /// @see ExecutionContext::HasFrameScope() const + //------------------------------------------------------------------ + StackFrame & + GetFrameRef () const; + + //------------------------------------------------------------------ + /// Get accessor to get the target shared pointer. + /// + /// The returned shared pointer is not guaranteed to be valid. + //------------------------------------------------------------------ + const lldb::TargetSP & + GetTargetSP () const + { + return m_target_sp; + } + + //------------------------------------------------------------------ + /// Get accessor to get the process shared pointer. + /// + /// The returned shared pointer is not guaranteed to be valid. + //------------------------------------------------------------------ + const lldb::ProcessSP & + GetProcessSP () const + { + return m_process_sp; + } + + //------------------------------------------------------------------ + /// Get accessor to get the thread shared pointer. + /// + /// The returned shared pointer is not guaranteed to be valid. + //------------------------------------------------------------------ + const lldb::ThreadSP & + GetThreadSP () const + { + return m_thread_sp; + } + + //------------------------------------------------------------------ + /// Get accessor to get the frame shared pointer. + /// + /// The returned shared pointer is not guaranteed to be valid. + //------------------------------------------------------------------ + const lldb::StackFrameSP & + GetFrameSP () const + { + return m_frame_sp; + } + + //------------------------------------------------------------------ + /// Set accessor to set only the target shared pointer. + //------------------------------------------------------------------ + void + SetTargetSP (const lldb::TargetSP &target_sp); + + //------------------------------------------------------------------ + /// Set accessor to set only the process shared pointer. + //------------------------------------------------------------------ + void + SetProcessSP (const lldb::ProcessSP &process_sp); + + //------------------------------------------------------------------ + /// Set accessor to set only the thread shared pointer. + //------------------------------------------------------------------ + void + SetThreadSP (const lldb::ThreadSP &thread_sp); + + //------------------------------------------------------------------ + /// Set accessor to set only the frame shared pointer. + //------------------------------------------------------------------ + void + SetFrameSP (const lldb::StackFrameSP &frame_sp); + + //------------------------------------------------------------------ + /// Set accessor to set only the target shared pointer from a target + /// pointer. + //------------------------------------------------------------------ + void + SetTargetPtr (Target* target); + + //------------------------------------------------------------------ + /// Set accessor to set only the process shared pointer from a + /// process pointer. + //------------------------------------------------------------------ + void + SetProcessPtr (Process *process); + + //------------------------------------------------------------------ + /// Set accessor to set only the thread shared pointer from a thread + /// pointer. + //------------------------------------------------------------------ + void + SetThreadPtr (Thread *thread); + + //------------------------------------------------------------------ + /// Set accessor to set only the frame shared pointer from a frame + /// pointer. + //------------------------------------------------------------------ + void + SetFramePtr (StackFrame *frame); + + //------------------------------------------------------------------ + // Set the execution context using a target shared pointer. + // + // If "target_sp" is valid, sets the target context to match and + // if "get_process" is true, sets the process shared pointer if + // the target currently has a process. + //------------------------------------------------------------------ + void + SetContext (const lldb::TargetSP &target_sp, bool get_process); + + //------------------------------------------------------------------ + // Set the execution context using a process shared pointer. + // + // If "process_sp" is valid, then set the process and target in this + // context. Thread and frame contexts will be cleared. + // If "process_sp" is not valid, all shared pointers are reset. + //------------------------------------------------------------------ + void + SetContext (const lldb::ProcessSP &process_sp); + + //------------------------------------------------------------------ + // Set the execution context using a thread shared pointer. + // + // If "thread_sp" is valid, then set the thread, process and target + // in this context. The frame context will be cleared. + // If "thread_sp" is not valid, all shared pointers are reset. + //------------------------------------------------------------------ + void + SetContext (const lldb::ThreadSP &thread_sp); + + //------------------------------------------------------------------ + // Set the execution context using a frame shared pointer. + // + // If "frame_sp" is valid, then set the frame, thread, process and + // target in this context + // If "frame_sp" is not valid, all shared pointers are reset. + //------------------------------------------------------------------ + void + SetContext (const lldb::StackFrameSP &frame_sp); + + //------------------------------------------------------------------ + /// Returns true the ExecutionContext object contains a valid + /// target. + /// + /// This function can be called after initializing an ExecutionContext + /// object, and if it returns true, calls to GetTargetPtr() and + /// GetTargetRef() do not need to be checked for validity. + //------------------------------------------------------------------ + bool + HasTargetScope () const; + + //------------------------------------------------------------------ + /// Returns true the ExecutionContext object contains a valid + /// target and process. + /// + /// This function can be called after initializing an ExecutionContext + /// object, and if it returns true, calls to GetTargetPtr() and + /// GetTargetRef(), GetProcessPtr(), and GetProcessRef(), do not + /// need to be checked for validity. + //------------------------------------------------------------------ + bool + HasProcessScope () const; + + //------------------------------------------------------------------ + /// Returns true the ExecutionContext object contains a valid + /// target, process, and thread. + /// + /// This function can be called after initializing an ExecutionContext + /// object, and if it returns true, calls to GetTargetPtr(), + /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(), + /// and GetThreadRef() do not need to be checked for validity. + //------------------------------------------------------------------ + bool + HasThreadScope () const; + + //------------------------------------------------------------------ + /// Returns true the ExecutionContext object contains a valid + /// target, process, thread and frame. + /// + /// This function can be called after initializing an ExecutionContext + /// object, and if it returns true, calls to GetTargetPtr(), + /// GetTargetRef(), GetProcessPtr(), GetProcessRef(), GetThreadPtr(), + /// GetThreadRef(), GetFramePtr(), and GetFrameRef() do not need + /// to be checked for validity. + //------------------------------------------------------------------ + bool + HasFrameScope () const; + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + lldb::TargetSP m_target_sp; ///< The target that owns the process/thread/frame + lldb::ProcessSP m_process_sp; ///< The process that owns the thread/frame + lldb::ThreadSP m_thread_sp; ///< The thread that owns the frame + lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread. +}; +} // namespace lldb_private + +#endif // liblldb_ExecutionContext_h_ diff --git a/include/lldb/Target/ExecutionContextScope.h b/include/lldb/Target/ExecutionContextScope.h new file mode 100644 index 0000000..7ba4097 --- /dev/null +++ b/include/lldb/Target/ExecutionContextScope.h @@ -0,0 +1,74 @@ +//===-- ExecutionContextScope.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_ExecutionContextScope_h_ +#define liblldb_ExecutionContextScope_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ExecutionContextScope ExecutionContextScope.h "lldb/Symbol/ExecutionContextScope.h" +/// @brief Inherit from this if your object can reconstruct its +/// execution context. +/// +/// Many objects that have pointers back to parent execution context +/// objects can inherit from this pure virtual class can reconstruct +/// their execution context without having to keep a complete +/// ExecutionContext object in the object state. Examples of these +/// objects include: Process, Thread, RegisterContext and StackFrame. +/// +/// Bbjects can contain a valid pointer to an instance of this so they +/// can reconstruct the execution context. +/// +/// Objects that adhere to this protocol can reconstruct enough of a +/// execution context to allow functions that take a execution contexts +/// to be called. +//---------------------------------------------------------------------- +class ExecutionContextScope +{ +public: + virtual + ~ExecutionContextScope () {} + + virtual lldb::TargetSP + CalculateTarget () = 0; + + virtual lldb::ProcessSP + CalculateProcess () = 0; + + virtual lldb::ThreadSP + CalculateThread () = 0; + + virtual lldb::StackFrameSP + CalculateStackFrame () = 0; + + //------------------------------------------------------------------ + /// Reconstruct the object's execution context into \a sc. + /// + /// The object should fill in as much of the ExecutionContextScope as it + /// can so function calls that require a execution context can be made + /// for the given object. + /// + /// @param[out] exe_ctx + /// A reference to an execution context object that gets filled + /// in. + //------------------------------------------------------------------ + virtual void + CalculateExecutionContext (ExecutionContext &exe_ctx) = 0; +}; + +} // namespace lldb_private + +#endif // liblldb_ExecutionContextScope_h_ diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h new file mode 100644 index 0000000..93c0437 --- /dev/null +++ b/include/lldb/Target/LanguageRuntime.h @@ -0,0 +1,113 @@ +//===-- LanguageRuntime.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_LanguageRuntime_h_ +#define liblldb_LanguageRuntime_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Breakpoint/BreakpointResolverName.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/Value.h" +#include "lldb/Target/ExecutionContextScope.h" + +namespace lldb_private { + +class LanguageRuntime : + public PluginInterface +{ +public: + virtual + ~LanguageRuntime(); + + static LanguageRuntime* + FindPlugin (Process *process, lldb::LanguageType language); + + virtual lldb::LanguageType + GetLanguageType () const = 0; + + virtual bool + GetObjectDescription (Stream &str, ValueObject &object) = 0; + + virtual bool + GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) = 0; + + // this call should return true if it could set the name and/or the type + virtual bool + GetDynamicTypeAndAddress (ValueObject &in_value, + lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, + Address &address) = 0; + + // This should be a fast test to determine whether it is likely that this value would + // have a dynamic type. + virtual bool + CouldHaveDynamicValue (ValueObject &in_value) = 0; + + virtual void + SetExceptionBreakpoints () + { + } + + virtual void + ClearExceptionBreakpoints () + { + } + + virtual bool + ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason) + { + return false; + } + + static lldb::BreakpointSP + CreateExceptionBreakpoint (Target &target, + lldb::LanguageType language, + bool catch_bp, + bool throw_bp, + bool is_internal = false); + + static lldb::LanguageType + GetLanguageTypeFromString (const char *string); + + static const char * + GetNameForLanguageType (lldb::LanguageType language); + + Process * + GetProcess() + { + return m_process; + } + + virtual lldb::BreakpointResolverSP + CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) = 0; + + virtual lldb::SearchFilterSP + CreateExceptionSearchFilter (); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from LanguageRuntime can see and modify these + //------------------------------------------------------------------ + + LanguageRuntime(Process *process); + Process *m_process; +private: + DISALLOW_COPY_AND_ASSIGN (LanguageRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_LanguageRuntime_h_ diff --git a/include/lldb/Target/Memory.h b/include/lldb/Target/Memory.h new file mode 100644 index 0000000..568bbcd --- /dev/null +++ b/include/lldb/Target/Memory.h @@ -0,0 +1,196 @@ +//===-- Memory.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_Memory_h_ +#define liblldb_Memory_h_ + +// C Includes +// C++ Includes +#include <map> +#include <vector> + +// Other libraries and framework includes + +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + //---------------------------------------------------------------------- + // A class to track memory that was read from a live process between + // runs. + //---------------------------------------------------------------------- + class MemoryCache + { + public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + MemoryCache (Process &process); + + ~MemoryCache (); + + void + Clear(bool clear_invalid_ranges = false); + + void + Flush (lldb::addr_t addr, size_t size); + + size_t + Read (lldb::addr_t addr, + void *dst, + size_t dst_len, + Error &error); + + uint32_t + GetMemoryCacheLineSize() const + { + return m_cache_line_byte_size ; + } + + void + AddInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size); + + bool + RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size); + + protected: + typedef std::map<lldb::addr_t, lldb::DataBufferSP> BlockMap; + typedef RangeArray<lldb::addr_t, lldb::addr_t, 4> InvalidRanges; + //------------------------------------------------------------------ + // Classes that inherit from MemoryCache can see and modify these + //------------------------------------------------------------------ + Process &m_process; + uint32_t m_cache_line_byte_size; + Mutex m_mutex; + BlockMap m_cache; + InvalidRanges m_invalid_ranges; + private: + DISALLOW_COPY_AND_ASSIGN (MemoryCache); + }; + + + class AllocatedBlock + { + public: + AllocatedBlock (lldb::addr_t addr, + uint32_t byte_size, + uint32_t permissions, + uint32_t chunk_size); + + ~AllocatedBlock (); + + lldb::addr_t + ReserveBlock (uint32_t size); + + bool + FreeBlock (lldb::addr_t addr); + + lldb::addr_t + GetBaseAddress () const + { + return m_addr; + } + + uint32_t + GetByteSize () const + { + return m_byte_size; + } + + uint32_t + GetPermissions () const + { + return m_permissions; + } + + uint32_t + GetChunkSize () const + { + return m_chunk_size; + } + + bool + Contains (lldb::addr_t addr) const + { + return ((addr >= m_addr) && addr < (m_addr + m_byte_size)); + } + protected: + uint32_t + TotalChunks () const + { + return m_byte_size / m_chunk_size; + } + + uint32_t + CalculateChunksNeededForSize (uint32_t size) const + { + return (size + m_chunk_size - 1) / m_chunk_size; + } + const lldb::addr_t m_addr; // Base address of this block of memory + const uint32_t m_byte_size; // 4GB of chunk should be enough... + const uint32_t m_permissions; // Permissions for this memory (logical OR of lldb::Permissions bits) + const uint32_t m_chunk_size; // The size of chunks that the memory at m_addr is divied up into + typedef std::map<uint32_t, uint32_t> OffsetToChunkSize; + OffsetToChunkSize m_offset_to_chunk_size; + }; + + + //---------------------------------------------------------------------- + // A class that can track allocated memory and give out allocated memory + // without us having to make an allocate/deallocate call every time we + // need some memory in a process that is being debugged. + //---------------------------------------------------------------------- + class AllocatedMemoryCache + { + public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + AllocatedMemoryCache (Process &process); + + ~AllocatedMemoryCache (); + + void + Clear(); + + lldb::addr_t + AllocateMemory (size_t byte_size, + uint32_t permissions, + Error &error); + + bool + DeallocateMemory (lldb::addr_t ptr); + + protected: + typedef std::shared_ptr<AllocatedBlock> AllocatedBlockSP; + + AllocatedBlockSP + AllocatePage (uint32_t byte_size, + uint32_t permissions, + uint32_t chunk_size, + Error &error); + + + //------------------------------------------------------------------ + // Classes that inherit from MemoryCache can see and modify these + //------------------------------------------------------------------ + Process &m_process; + Mutex m_mutex; + typedef std::multimap<uint32_t, AllocatedBlockSP> PermissionsToBlockMap; + PermissionsToBlockMap m_memory_map; + + private: + DISALLOW_COPY_AND_ASSIGN (AllocatedMemoryCache); + }; + +} // namespace lldb_private + +#endif // liblldb_Memory_h_ diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h new file mode 100644 index 0000000..7bac572 --- /dev/null +++ b/include/lldb/Target/ObjCLanguageRuntime.h @@ -0,0 +1,604 @@ +//===-- ObjCLanguageRuntime.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_ObjCLanguageRuntime_h_ +#define liblldb_ObjCLanguageRuntime_h_ + +// C Includes +// C++ Includes +#include <functional> +#include <map> +#include <unordered_set> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeVendor.h" +#include "lldb/Target/LanguageRuntime.h" + +namespace lldb_private { + +class ClangUtilityFunction; + +class ObjCLanguageRuntime : + public LanguageRuntime +{ +public: + class MethodName + { + public: + enum Type + { + eTypeUnspecified, + eTypeClassMethod, + eTypeInstanceMethod + }; + + MethodName () : + m_full(), + m_class(), + m_category(), + m_selector(), + m_type (eTypeUnspecified), + m_category_is_valid (false) + { + } + + MethodName (const char *name, bool strict) : + m_full(), + m_class(), + m_category(), + m_selector(), + m_type (eTypeUnspecified), + m_category_is_valid (false) + { + SetName (name, strict); + } + + void + Clear(); + + bool + IsValid (bool strict) const + { + // If "strict" is true, the name must have everything specified including + // the leading "+" or "-" on the method name + if (strict && m_type == eTypeUnspecified) + return false; + // Other than that, m_full will only be filled in if the objective C + // name is valid. + return (bool)m_full; + } + + bool + HasCategory() + { + return (bool)GetCategory(); + } + + Type + GetType () const + { + return m_type; + } + + const ConstString & + GetFullName () const + { + return m_full; + } + + ConstString + GetFullNameWithoutCategory (bool empty_if_no_category); + + bool + SetName (const char *name, bool strict); + + const ConstString & + GetClassName (); + + const ConstString & + GetClassNameWithCategory (); + + const ConstString & + GetCategory (); + + const ConstString & + GetSelector (); + + // Get all possible names for a method. Examples: + // If name is "+[NSString(my_additions) myStringWithCString:]" + // names[0] => "+[NSString(my_additions) myStringWithCString:]" + // names[1] => "+[NSString myStringWithCString:]" + // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]" + // names[0] => "+[NSString(my_additions) myStringWithCString:]" + // names[1] => "-[NSString(my_additions) myStringWithCString:]" + // names[2] => "+[NSString myStringWithCString:]" + // names[3] => "-[NSString myStringWithCString:]" + size_t + GetFullNames (std::vector<ConstString> &names, bool append); + protected: + ConstString m_full; // Full name: "+[NSString(my_additions) myStringWithCString:]" + ConstString m_class; // Class name: "NSString" + ConstString m_class_category; // Class with category: "NSString(my_additions)" + ConstString m_category; // Category: "my_additions" + ConstString m_selector; // Selector: "myStringWithCString:" + Type m_type; + bool m_category_is_valid; + + }; + typedef lldb::addr_t ObjCISA; + + class ClassDescriptor; + typedef std::shared_ptr<ClassDescriptor> ClassDescriptorSP; + + // the information that we want to support retrieving from an ObjC class + // this needs to be pure virtual since there are at least 2 different implementations + // of the runtime, and more might come + class ClassDescriptor + { + public: + + ClassDescriptor() : + m_is_kvo (eLazyBoolCalculate), + m_is_cf (eLazyBoolCalculate), + m_type_wp () + { + } + + virtual + ~ClassDescriptor () + { + } + + virtual ConstString + GetClassName () = 0; + + virtual ClassDescriptorSP + GetSuperclass () = 0; + + // virtual if any implementation has some other version-specific rules + // but for the known v1/v2 this is all that needs to be done + virtual bool + IsKVO () + { + if (m_is_kvo == eLazyBoolCalculate) + { + const char* class_name = GetClassName().AsCString(); + if (class_name && *class_name) + m_is_kvo = (LazyBool)(strstr(class_name,"NSKVONotifying_") == class_name); + } + return (m_is_kvo == eLazyBoolYes); + } + + // virtual if any implementation has some other version-specific rules + // but for the known v1/v2 this is all that needs to be done + virtual bool + IsCFType () + { + if (m_is_cf == eLazyBoolCalculate) + { + const char* class_name = GetClassName().AsCString(); + if (class_name && *class_name) + m_is_cf = (LazyBool)(strcmp(class_name,"__NSCFType") == 0 || + strcmp(class_name,"NSCFType") == 0); + } + return (m_is_cf == eLazyBoolYes); + } + + virtual bool + IsValid () = 0; + + virtual bool + GetTaggedPointerInfo (uint64_t* info_bits = NULL, + uint64_t* value_bits = NULL, + uint64_t* payload = NULL) = 0; + + virtual uint64_t + GetInstanceSize () = 0; + + // use to implement version-specific additional constraints on pointers + virtual bool + CheckPointer (lldb::addr_t value, + uint32_t ptr_size) const + { + return true; + } + + virtual ObjCISA + GetISA () = 0; + + // This should return true iff the interface could be completed + virtual bool + Describe (std::function <void (ObjCISA)> const &superclass_func, + std::function <bool (const char*, const char*)> const &instance_method_func, + std::function <bool (const char*, const char*)> const &class_method_func, + std::function <bool (const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) + { + return false; + } + + lldb::TypeSP + GetType () + { + return m_type_wp.lock(); + } + + void + SetType (const lldb::TypeSP &type_sp) + { + m_type_wp = type_sp; + } + + protected: + bool + IsPointerValid (lldb::addr_t value, + uint32_t ptr_size, + bool allow_NULLs = false, + bool allow_tagged = false, + bool check_version_specific = false) const; + + private: + LazyBool m_is_kvo; + LazyBool m_is_cf; + lldb::TypeWP m_type_wp; + }; + + virtual ClassDescriptorSP + GetClassDescriptor (ValueObject& in_value); + + ClassDescriptorSP + GetNonKVOClassDescriptor (ValueObject& in_value); + + virtual ClassDescriptorSP + GetClassDescriptorFromClassName (const ConstString &class_name); + + virtual ClassDescriptorSP + GetClassDescriptorFromISA (ObjCISA isa); + + ClassDescriptorSP + GetNonKVOClassDescriptor (ObjCISA isa); + + virtual + ~ObjCLanguageRuntime(); + + virtual lldb::LanguageType + GetLanguageType () const + { + return lldb::eLanguageTypeObjC; + } + + virtual bool + IsModuleObjCLibrary (const lldb::ModuleSP &module_sp) = 0; + + virtual bool + ReadObjCLibrary (const lldb::ModuleSP &module_sp) = 0; + + virtual bool + HasReadObjCLibrary () = 0; + + virtual lldb::ThreadPlanSP + GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) = 0; + + lldb::addr_t + LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t sel); + + void + AddToMethodCache (lldb::addr_t class_addr, lldb::addr_t sel, lldb::addr_t impl_addr); + + TypeAndOrName + LookupInClassNameCache (lldb::addr_t class_addr); + + void + AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp); + + void + AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_or_type_name); + + lldb::TypeSP + LookupInCompleteClassCache (ConstString &name); + + virtual ClangUtilityFunction * + CreateObjectChecker (const char *) = 0; + + virtual ObjCRuntimeVersions + GetRuntimeVersion () + { + return eObjC_VersionUnknown; + } + + bool + IsValidISA(ObjCISA isa) + { + UpdateISAToDescriptorMap(); + return m_isa_to_descriptor.count(isa) > 0; + } + + virtual void + UpdateISAToDescriptorMapIfNeeded() = 0; + + void + UpdateISAToDescriptorMap() + { + if (m_process && m_process->GetStopID() != m_isa_to_descriptor_stop_id) + { + UpdateISAToDescriptorMapIfNeeded (); + } + } + + virtual ObjCISA + GetISA(const ConstString &name); + + virtual ConstString + GetActualTypeName(ObjCISA isa); + + virtual ObjCISA + GetParentClass(ObjCISA isa); + + virtual TypeVendor * + GetTypeVendor() + { + return NULL; + } + + // Finds the byte offset of the child_type ivar in parent_type. If it can't find the + // offset, returns LLDB_INVALID_IVAR_OFFSET. + + virtual size_t + GetByteOffsetForIvar (ClangASTType &parent_qual_type, const char *ivar_name); + + // Given the name of an Objective-C runtime symbol (e.g., ivar offset symbol), + // try to determine from the runtime what the value of that symbol would be. + // Useful when the underlying binary is stripped. + virtual lldb::addr_t + LookupRuntimeSymbol (const ConstString &name) + { + return LLDB_INVALID_ADDRESS; + } + + //------------------------------------------------------------------ + /// Chop up an objective C function prototype. + /// + /// Chop up an objective C function fullname and optionally fill in + /// any non-NULL ConstString objects. If a ConstString * is NULL, + /// then this name doesn't get filled in + /// + /// @param[in] name + /// A fully specified objective C function name. The string might + /// contain a category and it includes the leading "+" or "-" and + /// the square brackets, no types for the arguments, just the plain + /// selector. A few examples: + /// "-[NSStringDrawingContext init]" + /// "-[NSStringDrawingContext addString:inRect:]" + /// "-[NSString(NSStringDrawing) sizeWithAttributes:]" + /// "+[NSString(NSStringDrawing) usesFontLeading]" + /// + /// @param[out] class_name + /// If non-NULL, this string will be filled in with the class + /// name including the category. The examples above would return: + /// "NSStringDrawingContext" + /// "NSStringDrawingContext" + /// "NSString(NSStringDrawing)" + /// "NSString(NSStringDrawing)" + /// + /// @param[out] selector_name + /// If non-NULL, this string will be filled in with the selector + /// name. The examples above would return: + /// "init" + /// "addString:inRect:" + /// "sizeWithAttributes:" + /// "usesFontLeading" + /// + /// @param[out] name_sans_category + /// If non-NULL, this string will be filled in with the class + /// name _without_ the category. If there is no category, and empty + /// string will be returned (as the result would be normally returned + /// in the "class_name" argument). The examples above would return: + /// <empty> + /// <empty> + /// "-[NSString sizeWithAttributes:]" + /// "+[NSString usesFontLeading]" + /// + /// @param[out] class_name_sans_category + /// If non-NULL, this string will be filled in with the prototype + /// name _without_ the category. If there is no category, and empty + /// string will be returned (as this is already the value that was + /// passed in). The examples above would return: + /// <empty> + /// <empty> + /// "NSString" + /// "NSString" + /// + /// @return + /// Returns the number of strings that were successfully filled + /// in. + //------------------------------------------------------------------ +// static uint32_t +// ParseMethodName (const char *name, +// ConstString *class_name, // Class name (with category if there is one) +// ConstString *selector_name, // selector only +// ConstString *name_sans_category, // full function name with no category (empty if no category) +// ConstString *class_name_sans_category);// Class name without category (empty if no category) + + static bool + IsPossibleObjCMethodName (const char *name) + { + if (!name) + return false; + bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; + bool ends_right = (name[strlen(name) - 1] == ']'); + return (starts_right && ends_right); + } + + static bool + IsPossibleObjCSelector (const char *name) + { + if (!name) + return false; + + if (strchr(name, ':') == NULL) + return true; + else if (name[strlen(name) - 1] == ':') + return true; + else + return false; + } + + bool + HasNewLiteralsAndIndexing () + { + if (m_has_new_literals_and_indexing == eLazyBoolCalculate) + { + if (CalculateHasNewLiteralsAndIndexing()) + m_has_new_literals_and_indexing = eLazyBoolYes; + else + m_has_new_literals_and_indexing = eLazyBoolNo; + } + + return (m_has_new_literals_and_indexing == eLazyBoolYes); + } + + virtual void + SymbolsDidLoad (const ModuleList& module_list) + { + m_negative_complete_class_cache.clear(); + } + +protected: + //------------------------------------------------------------------ + // Classes that inherit from ObjCLanguageRuntime can see and modify these + //------------------------------------------------------------------ + ObjCLanguageRuntime(Process *process); + + virtual bool CalculateHasNewLiteralsAndIndexing() + { + return false; + } + + + bool + ISAIsCached (ObjCISA isa) const + { + return m_isa_to_descriptor.find(isa) != m_isa_to_descriptor.end(); + } + + bool + AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp) + { + if (isa != 0) + { + m_isa_to_descriptor[isa] = descriptor_sp; + return true; + } + return false; + } + + bool + AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, const char *class_name); + + bool + AddClass (ObjCISA isa, const ClassDescriptorSP &descriptor_sp, uint32_t class_name_hash) + { + if (isa != 0) + { + m_isa_to_descriptor[isa] = descriptor_sp; + m_hash_to_isa_map.insert(std::make_pair(class_name_hash, isa)); + return true; + } + return false; + } + +private: + // We keep a map of <Class,Selector>->Implementation so we don't have to call the resolver + // function over and over. + + // FIXME: We need to watch for the loading of Protocols, and flush the cache for any + // class that we see so changed. + + struct ClassAndSel + { + ClassAndSel() + { + sel_addr = LLDB_INVALID_ADDRESS; + class_addr = LLDB_INVALID_ADDRESS; + } + ClassAndSel (lldb::addr_t in_sel_addr, lldb::addr_t in_class_addr) : + class_addr (in_class_addr), + sel_addr(in_sel_addr) + { + } + bool operator== (const ClassAndSel &rhs) + { + if (class_addr == rhs.class_addr + && sel_addr == rhs.sel_addr) + return true; + else + return false; + } + + bool operator< (const ClassAndSel &rhs) const + { + if (class_addr < rhs.class_addr) + return true; + else if (class_addr > rhs.class_addr) + return false; + else + { + if (sel_addr < rhs.sel_addr) + return true; + else + return false; + } + } + + lldb::addr_t class_addr; + lldb::addr_t sel_addr; + }; + + typedef std::map<ClassAndSel,lldb::addr_t> MsgImplMap; + typedef std::map<ObjCISA, ClassDescriptorSP> ISAToDescriptorMap; + typedef std::multimap<uint32_t, ObjCISA> HashToISAMap; + typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator; + typedef HashToISAMap::iterator HashToISAIterator; + + MsgImplMap m_impl_cache; + LazyBool m_has_new_literals_and_indexing; + ISAToDescriptorMap m_isa_to_descriptor; + HashToISAMap m_hash_to_isa_map; + +protected: + uint32_t m_isa_to_descriptor_stop_id; + + typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap; + CompleteClassMap m_complete_class_cache; + + struct ConstStringSetHelpers { + size_t operator () (const ConstString& arg) const // for hashing + { + return (size_t)arg.GetCString(); + } + bool operator () (const ConstString& arg1, const ConstString& arg2) const // for equality + { + return arg1.operator==(arg2); + } + }; + typedef std::unordered_set<ConstString, ConstStringSetHelpers, ConstStringSetHelpers> CompleteClassSet; + CompleteClassSet m_negative_complete_class_cache; + + ISAToDescriptorIterator + GetDescriptorIterator (const ConstString &name); + + DISALLOW_COPY_AND_ASSIGN (ObjCLanguageRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_ObjCLanguageRuntime_h_ diff --git a/include/lldb/Target/OperatingSystem.h b/include/lldb/Target/OperatingSystem.h new file mode 100644 index 0000000..f1c0eb0 --- /dev/null +++ b/include/lldb/Target/OperatingSystem.h @@ -0,0 +1,101 @@ +//===-- OperatingSystem.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_OperatingSystem_h_ +#define liblldb_OperatingSystem_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes + +#include "lldb/lldb-private.h" +#include "lldb/Core/PluginInterface.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class OperatingSystem OperatingSystem.h "lldb/Target/OperatingSystem.h" +/// @brief A plug-in interface definition class for halted OS helpers. +/// +/// Halted OS plug-ins can be used by any process to locate and create +/// OS objects, like threads, during the lifetime of a debug session. +/// This is commonly used when attaching to an operating system that is +/// halted, such as when debugging over JTAG or connecting to low level +/// kernel debug services. +//---------------------------------------------------------------------- + +class OperatingSystem : + public PluginInterface + +{ +public: + //------------------------------------------------------------------ + /// Find a halted OS plugin for a given process. + /// + /// Scans the installed OperatingSystem plug-ins and tries to find + /// an instance that matches the current target triple and + /// executable. + /// + /// @param[in] process + /// The process for which to try and locate a halted OS + /// plug-in instance. + /// + /// @param[in] plugin_name + /// An optional name of a specific halted OS plug-in that + /// should be used. If NULL, pick the best plug-in. + //------------------------------------------------------------------ + static OperatingSystem* + FindPlugin (Process *process, const char *plugin_name); + + //------------------------------------------------------------------ + // Class Methods + //------------------------------------------------------------------ + OperatingSystem (Process *process); + + virtual + ~OperatingSystem(); + + //------------------------------------------------------------------ + // Plug-in Methods + //------------------------------------------------------------------ + virtual bool + UpdateThreadList (ThreadList &old_thread_list, + ThreadList &real_thread_list, + ThreadList &new_thread_list) = 0; + + virtual void + ThreadWasSelected (Thread *thread) = 0; + + virtual lldb::RegisterContextSP + CreateRegisterContextForThread (Thread *thread, lldb::addr_t reg_data_addr) = 0; + + virtual lldb::StopInfoSP + CreateThreadStopReason (Thread *thread) = 0; + + virtual lldb::ThreadSP + CreateThread (lldb::tid_t tid, lldb::addr_t context) + { + return lldb::ThreadSP(); + } + + virtual bool + IsOperatingSystemPluginThread (const lldb::ThreadSP &thread_sp); + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + Process* m_process; ///< The process that this dynamic loader plug-in is tracking. +private: + DISALLOW_COPY_AND_ASSIGN (OperatingSystem); +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_OperatingSystem_h_ diff --git a/include/lldb/Target/PathMappingList.h b/include/lldb/Target/PathMappingList.h new file mode 100644 index 0000000..b5bcbbf --- /dev/null +++ b/include/lldb/Target/PathMappingList.h @@ -0,0 +1,171 @@ +//===-- PathMappingList.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_PathMappingList_h_ +#define liblldb_PathMappingList_h_ + +// C Includes +// C++ Includes +#include <map> +#include <vector> +// Other libraries and framework includes +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +// Project includes + +namespace lldb_private { + +class PathMappingList +{ +public: + + typedef void (*ChangedCallback) (const PathMappingList &path_list, + void *baton); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + PathMappingList (); + + PathMappingList (ChangedCallback callback, + void *callback_baton); + + PathMappingList (const PathMappingList &rhs); + + ~PathMappingList (); + + const PathMappingList & + operator =(const PathMappingList &rhs); + + void + Append (const ConstString &path, const ConstString &replacement, bool notify); + + void + Append (const PathMappingList &rhs, bool notify); + + void + Clear (bool notify); + + // By default, dump all pairs. + void + Dump (Stream *s, int pair_index=-1); + + bool + IsEmpty() const + { + return m_pairs.empty(); + } + + size_t + GetSize () const + { + return m_pairs.size(); + } + + bool + GetPathsAtIndex (uint32_t idx, ConstString &path, ConstString &new_path) const; + + void + Insert (const ConstString &path, + const ConstString &replacement, + uint32_t insert_idx, + bool notify); + + bool + Remove (off_t index, bool notify); + + bool + Remove (const ConstString &path, bool notify); + + bool + Replace (const ConstString &path, + const ConstString &replacement, + bool notify); + + bool + Replace (const ConstString &path, + const ConstString &replacement, + uint32_t index, + bool notify); + bool + RemapPath (const ConstString &path, ConstString &new_path) const; + + //------------------------------------------------------------------ + /// Remaps a source file given \a path into \a new_path. + /// + /// Remaps \a path if any source remappings match. This function + /// does NOT stat the file system so it can be used in tight loops + /// where debug info is being parsed. + /// + /// @param[in] path + /// The original source file path to try and remap. + /// + /// @param[out] new_path + /// The newly remapped filespec that is may or may not exist. + /// + /// @return + /// /b true if \a path was successfully located and \a new_path + /// is filled in with a new source path, \b false otherwise. + //------------------------------------------------------------------ + bool + RemapPath (const char *path, std::string &new_path) const; + + + //------------------------------------------------------------------ + /// Finds a source file given a file spec using the path remappings. + /// + /// Tries to resolve \a orig_spec by checking the path remappings. + /// It makes sure the file exists by checking with the file system, + /// so this call can be expensive if the remappings are on a network + /// or are even on the local file system, so use this function + /// sparingly (not in a tight debug info parsing loop). + /// + /// @param[in] orig_spec + /// The original source file path to try and remap. + /// + /// @param[out] new_spec + /// The newly remapped filespec that is guaranteed to exist. + /// + /// @return + /// /b true if \a orig_spec was successfully located and + /// \a new_spec is filled in with an existing file spec, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + FindFile (const FileSpec &orig_spec, FileSpec &new_spec) const; + + uint32_t + FindIndexForPath (const ConstString &path) const; + + uint32_t + GetModificationID() const + { + return m_mod_id; + } +protected: + typedef std::pair <ConstString, ConstString> pair; + typedef std::vector <pair> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + iterator + FindIteratorForPath (const ConstString &path); + + const_iterator + FindIteratorForPath (const ConstString &path) const; + + collection m_pairs; + ChangedCallback m_callback; + void * m_callback_baton; + uint32_t m_mod_id; // Incremented anytime anything is added or removed. +}; + +} // namespace lldb_private + +#endif // liblldb_PathMappingList_h_ diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h new file mode 100644 index 0000000..b0a0794 --- /dev/null +++ b/include/lldb/Target/Platform.h @@ -0,0 +1,755 @@ +//===-- Platform.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_Platform_h_ +#define liblldb_Platform_h_ + +// C Includes +// C++ Includes +#include <map> +#include <string> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + + //---------------------------------------------------------------------- + /// @class Platform Platform.h "lldb/Target/Platform.h" + /// @brief A plug-in interface definition class for debug platform that + /// includes many platform abilities such as: + /// @li getting platform information such as supported architectures, + /// supported binary file formats and more + /// @li launching new processes + /// @li attaching to existing processes + /// @li download/upload files + /// @li execute shell commands + /// @li listing and getting info for existing processes + /// @li attaching and possibly debugging the platform's kernel + //---------------------------------------------------------------------- + class Platform : public PluginInterface + { + public: + + //------------------------------------------------------------------ + /// Get the native host platform plug-in. + /// + /// There should only be one of these for each host that LLDB runs + /// upon that should be statically compiled in and registered using + /// preprocessor macros or other similar build mechanisms in a + /// PlatformSubclass::Initialize() function. + /// + /// This platform will be used as the default platform when launching + /// or attaching to processes unless another platform is specified. + //------------------------------------------------------------------ + static lldb::PlatformSP + GetDefaultPlatform (); + + static lldb::PlatformSP + GetPlatformForArchitecture (const ArchSpec &arch, + ArchSpec *platform_arch_ptr); + + static const char * + GetHostPlatformName (); + + static void + SetDefaultPlatform (const lldb::PlatformSP &platform_sp); + + static lldb::PlatformSP + Create (const char *platform_name, Error &error); + + static lldb::PlatformSP + Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error); + + static uint32_t + GetNumConnectedRemotePlatforms (); + + static lldb::PlatformSP + GetConnectedRemotePlatformAtIndex (uint32_t idx); + + //------------------------------------------------------------------ + /// Default Constructor + //------------------------------------------------------------------ + Platform (bool is_host_platform); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~Platform(); + + //------------------------------------------------------------------ + /// Find a platform plugin for a given process. + /// + /// Scans the installed Platform plug-ins and tries to find + /// an instance that can be used for \a process + /// + /// @param[in] process + /// The process for which to try and locate a platform + /// plug-in instance. + /// + /// @param[in] plugin_name + /// An optional name of a specific platform plug-in that + /// should be used. If NULL, pick the best plug-in. + //------------------------------------------------------------------ + static Platform* + FindPlugin (Process *process, const ConstString &plugin_name); + + //------------------------------------------------------------------ + /// Set the target's executable based off of the existing + /// architecture information in \a target given a path to an + /// executable \a exe_file. + /// + /// Each platform knows the architectures that it supports and can + /// select the correct architecture slice within \a exe_file by + /// inspecting the architecture in \a target. If the target had an + /// architecture specified, then in can try and obey that request + /// and optionally fail if the architecture doesn't match up. + /// If no architecture is specified, the platform should select the + /// default architecture from \a exe_file. Any application bundles + /// or executable wrappers can also be inspected for the actual + /// application binary within the bundle that should be used. + /// + /// @return + /// Returns \b true if this Platform plug-in was able to find + /// a suitable executable, \b false otherwise. + //------------------------------------------------------------------ + virtual Error + ResolveExecutable (const FileSpec &exe_file, + const ArchSpec &arch, + lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr); + + + //------------------------------------------------------------------ + /// Find a symbol file given a symbol file module specification. + /// + /// Each platform might have tricks to find symbol files for an + /// executable given information in a symbol file ModuleSpec. Some + /// platforms might also support symbol files that are bundles and + /// know how to extract the right symbol file given a bundle. + /// + /// @param[in] target + /// The target in which we are trying to resolve the symbol file. + /// The target has a list of modules that we might be able to + /// use in order to help find the right symbol file. If the + /// "m_file" or "m_platform_file" entries in the \a sym_spec + /// are filled in, then we might be able to locate a module in + /// the target, extract its UUID and locate a symbol file. + /// If just the "m_uuid" is specified, then we might be able + /// to find the module in the target that matches that UUID + /// and pair the symbol file along with it. If just "m_symbol_file" + /// is specified, we can use a variety of tricks to locate the + /// symbols in an SDK, PDK, or other development kit location. + /// + /// @param[in] sym_spec + /// A module spec that describes some information about the + /// symbol file we are trying to resolve. The ModuleSpec might + /// contain the following: + /// m_file - A full or partial path to an executable from the + /// target (might be empty). + /// m_platform_file - Another executable hint that contains + /// the path to the file as known on the + /// local/remote platform. + /// m_symbol_file - A full or partial path to a symbol file + /// or symbol bundle that should be used when + /// trying to resolve the symbol file. + /// m_arch - The architecture we are looking for when resolving + /// the symbol file. + /// m_uuid - The UUID of the executable and symbol file. This + /// can often be used to match up an exectuable with + /// a symbol file, or resolve an symbol file in a + /// symbol file bundle. + /// + /// @param[out] sym_file + /// The resolved symbol file spec if the returned error + /// indicates succes. + /// + /// @return + /// Returns an error that describes success or failure. + //------------------------------------------------------------------ + virtual Error + ResolveSymbolFile (Target &target, + const ModuleSpec &sym_spec, + FileSpec &sym_file); + + //------------------------------------------------------------------ + /// Resolves the FileSpec to a (possibly) remote path. Remote + /// platforms must override this to resolve to a path on the remote + /// side. + //------------------------------------------------------------------ + virtual bool + ResolveRemotePath (const FileSpec &platform_path, + FileSpec &resolved_platform_path); + + bool + GetOSVersion (uint32_t &major, + uint32_t &minor, + uint32_t &update); + + bool + SetOSVersion (uint32_t major, + uint32_t minor, + uint32_t update); + + bool + GetOSBuildString (std::string &s); + + bool + GetOSKernelDescription (std::string &s); + + // Returns the the hostname if we are connected, else the short plugin + // name. + ConstString + GetName (); + + virtual const char * + GetHostname (); + + virtual const char * + GetDescription () = 0; + + //------------------------------------------------------------------ + /// Report the current status for this platform. + /// + /// The returned string usually involves returning the OS version + /// (if available), and any SDK directory that might be being used + /// for local file caching, and if connected a quick blurb about + /// what this platform is connected to. + //------------------------------------------------------------------ + virtual void + GetStatus (Stream &strm); + + //------------------------------------------------------------------ + // Subclasses must be able to fetch the current OS version + // + // Remote classes must be connected for this to succeed. Local + // subclasses don't need to override this function as it will just + // call the Host::GetOSVersion(). + //------------------------------------------------------------------ + virtual bool + GetRemoteOSVersion () + { + return false; + } + + virtual bool + GetRemoteOSBuildString (std::string &s) + { + s.clear(); + return false; + } + + virtual bool + GetRemoteOSKernelDescription (std::string &s) + { + s.clear(); + return false; + } + + // Remote Platform subclasses need to override this function + virtual ArchSpec + GetRemoteSystemArchitecture () + { + return ArchSpec(); // Return an invalid architecture + } + + virtual const char * + GetUserName (uint32_t uid); + + virtual const char * + GetGroupName (uint32_t gid); + + //------------------------------------------------------------------ + /// Locate a file for a platform. + /// + /// The default implementation of this function will return the same + /// file patch in \a local_file as was in \a platform_file. + /// + /// @param[in] platform_file + /// The platform file path to locate and cache locally. + /// + /// @param[in] uuid_ptr + /// If we know the exact UUID of the file we are looking for, it + /// can be specified. If it is not specified, we might now know + /// the exact file. The UUID is usually some sort of MD5 checksum + /// for the file and is sometimes known by dynamic linkers/loaders. + /// If the UUID is known, it is best to supply it to platform + /// file queries to ensure we are finding the correct file, not + /// just a file at the correct path. + /// + /// @param[out] local_file + /// A locally cached version of the platform file. For platforms + /// that describe the current host computer, this will just be + /// the same file. For remote platforms, this file might come from + /// and SDK directory, or might need to be sync'ed over to the + /// current machine for efficient debugging access. + /// + /// @return + /// An error object. + //------------------------------------------------------------------ + virtual Error + GetFile (const FileSpec &platform_file, + const UUID *uuid_ptr, + FileSpec &local_file); + + //---------------------------------------------------------------------- + // Locate the scripting resource given a module specification. + // + // Locating the file should happen only on the local computer or using + // the current computers global settings. + //---------------------------------------------------------------------- + virtual FileSpecList + LocateExecutableScriptingResources (Target *target, + Module &module); + + virtual Error + GetSharedModule (const ModuleSpec &module_spec, + lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + lldb::ModuleSP *old_module_sp_ptr, + bool *did_create_ptr); + + virtual Error + ConnectRemote (Args& args); + + virtual Error + DisconnectRemote (); + + //------------------------------------------------------------------ + /// Get the platform's supported architectures in the order in which + /// they should be searched. + /// + /// @param[in] idx + /// A zero based architecture index + /// + /// @param[out] arch + /// A copy of the archgitecture at index if the return value is + /// \b true. + /// + /// @return + /// \b true if \a arch was filled in and is valid, \b false + /// otherwise. + //------------------------------------------------------------------ + virtual bool + GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) = 0; + + virtual size_t + GetSoftwareBreakpointTrapOpcode (Target &target, + BreakpointSite *bp_site) = 0; + + //------------------------------------------------------------------ + /// Launch a new process on a platform, not necessarily for + /// debugging, it could be just for running the process. + //------------------------------------------------------------------ + virtual Error + LaunchProcess (ProcessLaunchInfo &launch_info); + + //------------------------------------------------------------------ + /// Lets a platform answer if it is compatible with a given + /// architecture and the target triple contained within. + //------------------------------------------------------------------ + virtual bool + IsCompatibleArchitecture (const ArchSpec &arch, + bool exact_arch_match, + ArchSpec *compatible_arch_ptr); + + //------------------------------------------------------------------ + /// Not all platforms will support debugging a process by spawning + /// somehow halted for a debugger (specified using the + /// "eLaunchFlagDebug" launch flag) and then attaching. If your + /// platform doesn't support this, override this function and return + /// false. + //------------------------------------------------------------------ + virtual bool + CanDebugProcess () + { + return true; + } + + //------------------------------------------------------------------ + /// Subclasses should NOT need to implement this function as it uses + /// the Platform::LaunchProcess() followed by Platform::Attach () + //------------------------------------------------------------------ + lldb::ProcessSP + DebugProcess (ProcessLaunchInfo &launch_info, + Debugger &debugger, + Target *target, // Can be NULL, if NULL create a new target, else use existing one + Listener &listener, + Error &error); + + //------------------------------------------------------------------ + /// Attach to an existing process using a process ID. + /// + /// Each platform subclass needs to implement this function and + /// attempt to attach to the process with the process ID of \a pid. + /// The platform subclass should return an appropriate ProcessSP + /// subclass that is attached to the process, or an empty shared + /// pointer with an appriopriate error. + /// + /// @param[in] pid + /// The process ID that we should attempt to attach to. + /// + /// @return + /// An appropriate ProcessSP containing a valid shared pointer + /// to the default Process subclass for the platform that is + /// attached to the process, or an empty shared pointer with an + /// appriopriate error fill into the \a error object. + //------------------------------------------------------------------ + virtual lldb::ProcessSP + Attach (ProcessAttachInfo &attach_info, + Debugger &debugger, + Target *target, // Can be NULL, if NULL create a new target, else use existing one + Listener &listener, + Error &error) = 0; + + //------------------------------------------------------------------ + /// Attach to an existing process by process name. + /// + /// This function is not meant to be overridden by Process + /// subclasses. It will first call + /// Process::WillAttach (const char *) and if that returns \b + /// true, Process::DoAttach (const char *) will be called to + /// actually do the attach. If DoAttach returns \b true, then + /// Process::DidAttach() will be called. + /// + /// @param[in] process_name + /// A process name to match against the current process list. + /// + /// @return + /// Returns \a pid if attaching was successful, or + /// LLDB_INVALID_PROCESS_ID if attaching fails. + //------------------------------------------------------------------ +// virtual lldb::ProcessSP +// Attach (const char *process_name, +// bool wait_for_launch, +// Error &error) = 0; + + //------------------------------------------------------------------ + // The base class Platform will take care of the host platform. + // Subclasses will need to fill in the remote case. + //------------------------------------------------------------------ + virtual uint32_t + FindProcesses (const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &proc_infos); + + virtual bool + GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info); + + //------------------------------------------------------------------ + // Set a breakpoint on all functions that can end up creating a thread + // for this platform. This is needed when running expressions and + // also for process control. + //------------------------------------------------------------------ + virtual lldb::BreakpointSP + SetThreadCreationBreakpoint (Target &target); + + + const std::string & + GetRemoteURL () const + { + return m_remote_url; + } + + bool + IsHost () const + { + return m_is_host; // Is this the default host platform? + } + + bool + IsRemote () const + { + return !m_is_host; + } + + virtual bool + IsConnected () const + { + // Remote subclasses should override this function + return IsHost(); + } + + const ArchSpec & + GetSystemArchitecture(); + + void + SetSystemArchitecture (const ArchSpec &arch) + { + m_system_arch = arch; + if (IsHost()) + m_os_version_set_while_connected = m_system_arch.IsValid(); + } + + // Used for column widths + size_t + GetMaxUserIDNameLength() const + { + return m_max_uid_name_len; + } + // Used for column widths + size_t + GetMaxGroupIDNameLength() const + { + return m_max_gid_name_len; + } + + const ConstString & + GetSDKRootDirectory () const + { + return m_sdk_sysroot; + } + + void + SetSDKRootDirectory (const ConstString &dir) + { + m_sdk_sysroot = dir; + } + + const ConstString & + GetSDKBuild () const + { + return m_sdk_build; + } + + void + SetSDKBuild (const ConstString &sdk_build) + { + m_sdk_build = sdk_build; + } + + // There may be modules that we don't want to find by default for operations like "setting breakpoint by name". + // The platform will return "true" from this call if the passed in module happens to be one of these. + + virtual bool + ModuleIsExcludedForNonModuleSpecificSearches (Target &target, const lldb::ModuleSP &module_sp) + { + return false; + } + + virtual size_t + GetEnvironment (StringList &environment); + + protected: + bool m_is_host; + // Set to true when we are able to actually set the OS version while + // being connected. For remote platforms, we might set the version ahead + // of time before we actually connect and this version might change when + // we actually connect to a remote platform. For the host platform this + // will be set to the once we call Host::GetOSVersion(). + bool m_os_version_set_while_connected; + bool m_system_arch_set_while_connected; + ConstString m_sdk_sysroot; // the root location of where the SDK files are all located + ConstString m_sdk_build; + std::string m_remote_url; + std::string m_name; + uint32_t m_major_os_version; + uint32_t m_minor_os_version; + uint32_t m_update_os_version; + ArchSpec m_system_arch; // The architecture of the kernel or the remote platform + typedef std::map<uint32_t, ConstString> IDToNameMap; + Mutex m_uid_map_mutex; + Mutex m_gid_map_mutex; + IDToNameMap m_uid_map; + IDToNameMap m_gid_map; + size_t m_max_uid_name_len; + size_t m_max_gid_name_len; + + const char * + GetCachedUserName (uint32_t uid) + { + Mutex::Locker locker (m_uid_map_mutex); + IDToNameMap::iterator pos = m_uid_map.find (uid); + if (pos != m_uid_map.end()) + { + // return the empty string if our string is NULL + // so we can tell when things were in the negative + // cached (didn't find a valid user name, don't keep + // trying) + return pos->second.AsCString(""); + } + return NULL; + } + + const char * + SetCachedUserName (uint32_t uid, const char *name, size_t name_len) + { + Mutex::Locker locker (m_uid_map_mutex); + ConstString const_name (name); + m_uid_map[uid] = const_name; + if (m_max_uid_name_len < name_len) + m_max_uid_name_len = name_len; + // Const strings lives forever in our const string pool, so we can return the const char * + return const_name.GetCString(); + } + + void + SetUserNameNotFound (uint32_t uid) + { + Mutex::Locker locker (m_uid_map_mutex); + m_uid_map[uid] = ConstString(); + } + + + void + ClearCachedUserNames () + { + Mutex::Locker locker (m_uid_map_mutex); + m_uid_map.clear(); + } + + const char * + GetCachedGroupName (uint32_t gid) + { + Mutex::Locker locker (m_gid_map_mutex); + IDToNameMap::iterator pos = m_gid_map.find (gid); + if (pos != m_gid_map.end()) + { + // return the empty string if our string is NULL + // so we can tell when things were in the negative + // cached (didn't find a valid group name, don't keep + // trying) + return pos->second.AsCString(""); + } + return NULL; + } + + const char * + SetCachedGroupName (uint32_t gid, const char *name, size_t name_len) + { + Mutex::Locker locker (m_gid_map_mutex); + ConstString const_name (name); + m_gid_map[gid] = const_name; + if (m_max_gid_name_len < name_len) + m_max_gid_name_len = name_len; + // Const strings lives forever in our const string pool, so we can return the const char * + return const_name.GetCString(); + } + + void + SetGroupNameNotFound (uint32_t gid) + { + Mutex::Locker locker (m_gid_map_mutex); + m_gid_map[gid] = ConstString(); + } + + void + ClearCachedGroupNames () + { + Mutex::Locker locker (m_gid_map_mutex); + m_gid_map.clear(); + } + + private: + DISALLOW_COPY_AND_ASSIGN (Platform); + }; + + + class PlatformList + { + public: + PlatformList() : + m_mutex (Mutex::eMutexTypeRecursive), + m_platforms (), + m_selected_platform_sp() + { + } + + ~PlatformList() + { + } + + void + Append (const lldb::PlatformSP &platform_sp, bool set_selected) + { + Mutex::Locker locker (m_mutex); + m_platforms.push_back (platform_sp); + if (set_selected) + m_selected_platform_sp = m_platforms.back(); + } + + size_t + GetSize() + { + Mutex::Locker locker (m_mutex); + return m_platforms.size(); + } + + lldb::PlatformSP + GetAtIndex (uint32_t idx) + { + lldb::PlatformSP platform_sp; + { + Mutex::Locker locker (m_mutex); + if (idx < m_platforms.size()) + platform_sp = m_platforms[idx]; + } + return platform_sp; + } + + //------------------------------------------------------------------ + /// Select the active platform. + /// + /// In order to debug remotely, other platform's can be remotely + /// connected to and set as the selected platform for any subsequent + /// debugging. This allows connection to remote targets and allows + /// the ability to discover process info, launch and attach to remote + /// processes. + //------------------------------------------------------------------ + lldb::PlatformSP + GetSelectedPlatform () + { + Mutex::Locker locker (m_mutex); + if (!m_selected_platform_sp && !m_platforms.empty()) + m_selected_platform_sp = m_platforms.front(); + + return m_selected_platform_sp; + } + + void + SetSelectedPlatform (const lldb::PlatformSP &platform_sp) + { + if (platform_sp) + { + Mutex::Locker locker (m_mutex); + const size_t num_platforms = m_platforms.size(); + for (size_t idx=0; idx<num_platforms; ++idx) + { + if (m_platforms[idx].get() == platform_sp.get()) + { + m_selected_platform_sp = m_platforms[idx]; + return; + } + } + m_platforms.push_back (platform_sp); + m_selected_platform_sp = m_platforms.back(); + } + } + + protected: + typedef std::vector<lldb::PlatformSP> collection; + mutable Mutex m_mutex; + collection m_platforms; + lldb::PlatformSP m_selected_platform_sp; + + private: + DISALLOW_COPY_AND_ASSIGN (PlatformList); + }; +} // namespace lldb_private + +#endif // liblldb_Platform_h_ diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h new file mode 100644 index 0000000..ef89a1e --- /dev/null +++ b/include/lldb/Target/Process.h @@ -0,0 +1,3786 @@ +//===-- Process.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_Process_h_ +#define liblldb_Process_h_ + +// C Includes +#include <limits.h> +#include <spawn.h> + +// C++ Includes +#include <list> +#include <iosfwd> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Communication.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Event.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/StringList.h" +#include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Core/UserSettingsController.h" +#include "lldb/Breakpoint/BreakpointSiteList.h" +#include "lldb/Expression/ClangPersistentVariables.h" +#include "lldb/Expression/IRDynamicChecks.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/ProcessRunLock.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Interpreter/Options.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/Memory.h" +#include "lldb/Target/ThreadList.h" +#include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/PseudoTerminal.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// ProcessProperties +//---------------------------------------------------------------------- +class ProcessProperties : public Properties +{ +public: + ProcessProperties(bool is_global); + + virtual + ~ProcessProperties(); + + bool + GetDisableMemoryCache() const; + + Args + GetExtraStartupCommands () const; + + void + SetExtraStartupCommands (const Args &args); + + FileSpec + GetPythonOSPluginPath () const; + + void + SetPythonOSPluginPath (const FileSpec &file); + + bool + GetIgnoreBreakpointsInExpressions () const; + + void + SetIgnoreBreakpointsInExpressions (bool ignore); + + bool + GetUnwindOnErrorInExpressions () const; + + void + SetUnwindOnErrorInExpressions (bool ignore); + + bool + GetStopOnSharedLibraryEvents () const; + + void + SetStopOnSharedLibraryEvents (bool stop); + + bool + GetDetachKeepsStopped () const; + + void + SetDetachKeepsStopped (bool keep_stopped); +}; + +typedef std::shared_ptr<ProcessProperties> ProcessPropertiesSP; + +//---------------------------------------------------------------------- +// ProcessInfo +// +// A base class for information for a process. This can be used to fill +// out information for a process prior to launching it, or it can be +// used for an instance of a process and can be filled in with the +// existing values for that process. +//---------------------------------------------------------------------- +class ProcessInfo +{ +public: + ProcessInfo () : + m_executable (), + m_arguments (), + m_environment (), + m_uid (UINT32_MAX), + m_gid (UINT32_MAX), + m_arch(), + m_pid (LLDB_INVALID_PROCESS_ID) + { + } + + ProcessInfo (const char *name, + const ArchSpec &arch, + lldb::pid_t pid) : + m_executable (name, false), + m_arguments (), + m_environment(), + m_uid (UINT32_MAX), + m_gid (UINT32_MAX), + m_arch (arch), + m_pid (pid) + { + } + + void + Clear () + { + m_executable.Clear(); + m_arguments.Clear(); + m_environment.Clear(); + m_uid = UINT32_MAX; + m_gid = UINT32_MAX; + m_arch.Clear(); + m_pid = LLDB_INVALID_PROCESS_ID; + } + + const char * + GetName() const + { + return m_executable.GetFilename().GetCString(); + } + + size_t + GetNameLength() const + { + return m_executable.GetFilename().GetLength(); + } + + FileSpec & + GetExecutableFile () + { + return m_executable; + } + + void + SetExecutableFile (const FileSpec &exe_file, bool add_exe_file_as_first_arg) + { + if (exe_file) + { + m_executable = exe_file; + if (add_exe_file_as_first_arg) + { + char filename[PATH_MAX]; + if (exe_file.GetPath(filename, sizeof(filename))) + m_arguments.InsertArgumentAtIndex (0, filename); + } + } + else + { + m_executable.Clear(); + } + } + + const FileSpec & + GetExecutableFile () const + { + return m_executable; + } + + uint32_t + GetUserID() const + { + return m_uid; + } + + uint32_t + GetGroupID() const + { + return m_gid; + } + + bool + UserIDIsValid () const + { + return m_uid != UINT32_MAX; + } + + bool + GroupIDIsValid () const + { + return m_gid != UINT32_MAX; + } + + void + SetUserID (uint32_t uid) + { + m_uid = uid; + } + + void + SetGroupID (uint32_t gid) + { + m_gid = gid; + } + + ArchSpec & + GetArchitecture () + { + return m_arch; + } + + const ArchSpec & + GetArchitecture () const + { + return m_arch; + } + + lldb::pid_t + GetProcessID () const + { + return m_pid; + } + + void + SetProcessID (lldb::pid_t pid) + { + m_pid = pid; + } + + bool + ProcessIDIsValid() const + { + return m_pid != LLDB_INVALID_PROCESS_ID; + } + + void + Dump (Stream &s, Platform *platform) const; + + Args & + GetArguments () + { + return m_arguments; + } + + const Args & + GetArguments () const + { + return m_arguments; + } + + const char * + GetArg0 () const + { + if (m_arg0.empty()) + return NULL; + return m_arg0.c_str(); + } + + void + SetArg0 (const char *arg) + { + if (arg && arg[0]) + m_arg0 = arg; + else + m_arg0.clear(); + } + + void + SetArguments (const Args& args, bool first_arg_is_executable); + + void + SetArguments (char const **argv, bool first_arg_is_executable); + + Args & + GetEnvironmentEntries () + { + return m_environment; + } + + const Args & + GetEnvironmentEntries () const + { + return m_environment; + } + +protected: + FileSpec m_executable; + std::string m_arg0; // argv[0] if supported. If empty, then use m_executable. + // Not all process plug-ins support specifying an argv[0] + // that differs from the resolved platform executable + // (which is in m_executable) + Args m_arguments; // All program arguments except argv[0] + Args m_environment; + uint32_t m_uid; + uint32_t m_gid; + ArchSpec m_arch; + lldb::pid_t m_pid; +}; + +//---------------------------------------------------------------------- +// ProcessInstanceInfo +// +// Describes an existing process and any discoverable information that +// pertains to that process. +//---------------------------------------------------------------------- +class ProcessInstanceInfo : public ProcessInfo +{ +public: + ProcessInstanceInfo () : + ProcessInfo (), + m_euid (UINT32_MAX), + m_egid (UINT32_MAX), + m_parent_pid (LLDB_INVALID_PROCESS_ID) + { + } + + ProcessInstanceInfo (const char *name, + const ArchSpec &arch, + lldb::pid_t pid) : + ProcessInfo (name, arch, pid), + m_euid (UINT32_MAX), + m_egid (UINT32_MAX), + m_parent_pid (LLDB_INVALID_PROCESS_ID) + { + } + + void + Clear () + { + ProcessInfo::Clear(); + m_euid = UINT32_MAX; + m_egid = UINT32_MAX; + m_parent_pid = LLDB_INVALID_PROCESS_ID; + } + + uint32_t + GetEffectiveUserID() const + { + return m_euid; + } + + uint32_t + GetEffectiveGroupID() const + { + return m_egid; + } + + bool + EffectiveUserIDIsValid () const + { + return m_euid != UINT32_MAX; + } + + bool + EffectiveGroupIDIsValid () const + { + return m_egid != UINT32_MAX; + } + + void + SetEffectiveUserID (uint32_t uid) + { + m_euid = uid; + } + + void + SetEffectiveGroupID (uint32_t gid) + { + m_egid = gid; + } + + lldb::pid_t + GetParentProcessID () const + { + return m_parent_pid; + } + + void + SetParentProcessID (lldb::pid_t pid) + { + m_parent_pid = pid; + } + + bool + ParentProcessIDIsValid() const + { + return m_parent_pid != LLDB_INVALID_PROCESS_ID; + } + + void + Dump (Stream &s, Platform *platform) const; + + static void + DumpTableHeader (Stream &s, Platform *platform, bool show_args, bool verbose); + + void + DumpAsTableRow (Stream &s, Platform *platform, bool show_args, bool verbose) const; + +protected: + uint32_t m_euid; + uint32_t m_egid; + lldb::pid_t m_parent_pid; +}; + + +//---------------------------------------------------------------------- +// ProcessLaunchInfo +// +// Describes any information that is required to launch a process. +//---------------------------------------------------------------------- + +class ProcessLaunchInfo : public ProcessInfo +{ +public: + + class FileAction + { + public: + enum Action + { + eFileActionNone, + eFileActionClose, + eFileActionDuplicate, + eFileActionOpen + }; + + + FileAction () : + m_action (eFileActionNone), + m_fd (-1), + m_arg (-1), + m_path () + { + } + + void + Clear() + { + m_action = eFileActionNone; + m_fd = -1; + m_arg = -1; + m_path.clear(); + } + + bool + Close (int fd); + + bool + Duplicate (int fd, int dup_fd); + + bool + Open (int fd, const char *path, bool read, bool write); + + static bool + AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions, + const FileAction *info, + Log *log, + Error& error); + + int + GetFD () const + { + return m_fd; + } + + Action + GetAction () const + { + return m_action; + } + + int + GetActionArgument () const + { + return m_arg; + } + + const char * + GetPath () const + { + if (m_path.empty()) + return NULL; + return m_path.c_str(); + } + + protected: + Action m_action; // The action for this file + int m_fd; // An existing file descriptor + int m_arg; // oflag for eFileActionOpen*, dup_fd for eFileActionDuplicate + std::string m_path; // A file path to use for opening after fork or posix_spawn + }; + + ProcessLaunchInfo () : + ProcessInfo(), + m_working_dir (), + m_plugin_name (), + m_shell (), + m_flags (0), + m_file_actions (), + m_pty (), + m_resume_count (0), + m_monitor_callback (NULL), + m_monitor_callback_baton (NULL), + m_monitor_signals (false) + { + } + + ProcessLaunchInfo (const char *stdin_path, + const char *stdout_path, + const char *stderr_path, + const char *working_directory, + uint32_t launch_flags) : + ProcessInfo(), + m_working_dir (), + m_plugin_name (), + m_shell (), + m_flags (launch_flags), + m_file_actions (), + m_pty (), + m_resume_count (0), + m_monitor_callback (NULL), + m_monitor_callback_baton (NULL), + m_monitor_signals (false) + { + if (stdin_path) + { + ProcessLaunchInfo::FileAction file_action; + const bool read = true; + const bool write = false; + if (file_action.Open(STDIN_FILENO, stdin_path, read, write)) + AppendFileAction (file_action); + } + if (stdout_path) + { + ProcessLaunchInfo::FileAction file_action; + const bool read = false; + const bool write = true; + if (file_action.Open(STDOUT_FILENO, stdout_path, read, write)) + AppendFileAction (file_action); + } + if (stderr_path) + { + ProcessLaunchInfo::FileAction file_action; + const bool read = false; + const bool write = true; + if (file_action.Open(STDERR_FILENO, stderr_path, read, write)) + AppendFileAction (file_action); + } + if (working_directory) + SetWorkingDirectory(working_directory); + } + + void + AppendFileAction (const FileAction &info) + { + m_file_actions.push_back(info); + } + + bool + AppendCloseFileAction (int fd) + { + FileAction file_action; + if (file_action.Close (fd)) + { + AppendFileAction (file_action); + return true; + } + return false; + } + + bool + AppendDuplicateFileAction (int fd, int dup_fd) + { + FileAction file_action; + if (file_action.Duplicate (fd, dup_fd)) + { + AppendFileAction (file_action); + return true; + } + return false; + } + + bool + AppendOpenFileAction (int fd, const char *path, bool read, bool write) + { + FileAction file_action; + if (file_action.Open (fd, path, read, write)) + { + AppendFileAction (file_action); + return true; + } + return false; + } + + bool + AppendSuppressFileAction (int fd, bool read, bool write) + { + FileAction file_action; + if (file_action.Open (fd, "/dev/null", read, write)) + { + AppendFileAction (file_action); + return true; + } + return false; + } + + void + FinalizeFileActions (Target *target, + bool default_to_use_pty); + + size_t + GetNumFileActions () const + { + return m_file_actions.size(); + } + + const FileAction * + GetFileActionAtIndex (size_t idx) const + { + if (idx < m_file_actions.size()) + return &m_file_actions[idx]; + return NULL; + } + + const FileAction * + GetFileActionForFD (int fd) const + { + for (size_t idx=0, count=m_file_actions.size(); idx < count; ++idx) + { + if (m_file_actions[idx].GetFD () == fd) + return &m_file_actions[idx]; + } + return NULL; + } + + Flags & + GetFlags () + { + return m_flags; + } + + const Flags & + GetFlags () const + { + return m_flags; + } + + const char * + GetWorkingDirectory () const + { + if (m_working_dir.empty()) + return NULL; + return m_working_dir.c_str(); + } + + void + SetWorkingDirectory (const char *working_dir) + { + if (working_dir && working_dir[0]) + m_working_dir.assign (working_dir); + else + m_working_dir.clear(); + } + + void + SwapWorkingDirectory (std::string &working_dir) + { + m_working_dir.swap (working_dir); + } + + + const char * + GetProcessPluginName () const + { + if (m_plugin_name.empty()) + return NULL; + return m_plugin_name.c_str(); + } + + void + SetProcessPluginName (const char *plugin) + { + if (plugin && plugin[0]) + m_plugin_name.assign (plugin); + else + m_plugin_name.clear(); + } + + const char * + GetShell () const + { + if (m_shell.empty()) + return NULL; + return m_shell.c_str(); + } + + void + SetShell (const char * path) + { + if (path && path[0]) + { + m_shell.assign (path); + m_flags.Set (lldb::eLaunchFlagLaunchInShell); + } + else + { + m_shell.clear(); + m_flags.Clear (lldb::eLaunchFlagLaunchInShell); + } + } + + uint32_t + GetResumeCount () const + { + return m_resume_count; + } + + void + SetResumeCount (uint32_t c) + { + m_resume_count = c; + } + + bool + GetLaunchInSeparateProcessGroup () + { + return m_flags.Test(lldb::eLaunchFlagLaunchInSeparateProcessGroup); + } + + void + SetLaunchInSeparateProcessGroup (bool separate) + { + if (separate) + m_flags.Set(lldb::eLaunchFlagLaunchInSeparateProcessGroup); + else + m_flags.Clear (lldb::eLaunchFlagLaunchInSeparateProcessGroup); + + } + + void + Clear () + { + ProcessInfo::Clear(); + m_working_dir.clear(); + m_plugin_name.clear(); + m_shell.clear(); + m_flags.Clear(); + m_file_actions.clear(); + m_resume_count = 0; + } + + bool + ConvertArgumentsForLaunchingInShell (Error &error, + bool localhost, + bool will_debug, + bool first_arg_is_full_shell_command); + + void + SetMonitorProcessCallback (Host::MonitorChildProcessCallback callback, + void *baton, + bool monitor_signals) + { + m_monitor_callback = callback; + m_monitor_callback_baton = baton; + m_monitor_signals = monitor_signals; + } + + bool + MonitorProcess () const + { + if (m_monitor_callback && ProcessIDIsValid()) + { + Host::StartMonitoringChildProcess (m_monitor_callback, + m_monitor_callback_baton, + GetProcessID(), + m_monitor_signals); + return true; + } + return false; + } + + lldb_utility::PseudoTerminal & + GetPTY () + { + return m_pty; + } + +protected: + std::string m_working_dir; + std::string m_plugin_name; + std::string m_shell; + Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags + std::vector<FileAction> m_file_actions; // File actions for any other files + lldb_utility::PseudoTerminal m_pty; + uint32_t m_resume_count; // How many times do we resume after launching + Host::MonitorChildProcessCallback m_monitor_callback; + void *m_monitor_callback_baton; + bool m_monitor_signals; + +}; + +//---------------------------------------------------------------------- +// ProcessLaunchInfo +// +// Describes any information that is required to launch a process. +//---------------------------------------------------------------------- + +class ProcessAttachInfo : public ProcessInstanceInfo +{ +public: + ProcessAttachInfo() : + ProcessInstanceInfo(), + m_plugin_name (), + m_resume_count (0), + m_wait_for_launch (false), + m_ignore_existing (true), + m_continue_once_attached (false) + { + } + + ProcessAttachInfo (const ProcessLaunchInfo &launch_info) : + ProcessInstanceInfo(), + m_plugin_name (), + m_resume_count (0), + m_wait_for_launch (false), + m_ignore_existing (true), + m_continue_once_attached (false) + { + ProcessInfo::operator= (launch_info); + SetProcessPluginName (launch_info.GetProcessPluginName()); + SetResumeCount (launch_info.GetResumeCount()); + } + + bool + GetWaitForLaunch () const + { + return m_wait_for_launch; + } + + void + SetWaitForLaunch (bool b) + { + m_wait_for_launch = b; + } + + bool + GetIgnoreExisting () const + { + return m_ignore_existing; + } + + void + SetIgnoreExisting (bool b) + { + m_ignore_existing = b; + } + + bool + GetContinueOnceAttached () const + { + return m_continue_once_attached; + } + + void + SetContinueOnceAttached (bool b) + { + m_continue_once_attached = b; + } + + uint32_t + GetResumeCount () const + { + return m_resume_count; + } + + void + SetResumeCount (uint32_t c) + { + m_resume_count = c; + } + + const char * + GetProcessPluginName () const + { + if (m_plugin_name.empty()) + return NULL; + return m_plugin_name.c_str(); + } + + void + SetProcessPluginName (const char *plugin) + { + if (plugin && plugin[0]) + m_plugin_name.assign (plugin); + else + m_plugin_name.clear(); + } + + void + Clear () + { + ProcessInstanceInfo::Clear(); + m_plugin_name.clear(); + m_resume_count = 0; + m_wait_for_launch = false; + m_ignore_existing = true; + m_continue_once_attached = false; + } + + bool + ProcessInfoSpecified () const + { + if (GetExecutableFile()) + return true; + if (GetProcessID() != LLDB_INVALID_PROCESS_ID) + return true; + if (GetParentProcessID() != LLDB_INVALID_PROCESS_ID) + return true; + return false; + } +protected: + std::string m_plugin_name; + uint32_t m_resume_count; // How many times do we resume after launching + bool m_wait_for_launch; + bool m_ignore_existing; + bool m_continue_once_attached; // Supports the use-case scenario of immediately continuing the process once attached. +}; + +class ProcessLaunchCommandOptions : public Options +{ +public: + + ProcessLaunchCommandOptions (CommandInterpreter &interpreter) : + Options(interpreter) + { + // Keep default values of all options in one place: OptionParsingStarting () + OptionParsingStarting (); + } + + ~ProcessLaunchCommandOptions () + { + } + + Error + SetOptionValue (uint32_t option_idx, const char *option_arg); + + void + OptionParsingStarting () + { + launch_info.Clear(); + } + + const OptionDefinition* + GetDefinitions () + { + return g_option_table; + } + + // Options table: Required for subclasses of Options. + + static OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + ProcessLaunchInfo launch_info; +}; + +//---------------------------------------------------------------------- +// ProcessInstanceInfoMatch +// +// A class to help matching one ProcessInstanceInfo to another. +//---------------------------------------------------------------------- + +class ProcessInstanceInfoMatch +{ +public: + ProcessInstanceInfoMatch () : + m_match_info (), + m_name_match_type (eNameMatchIgnore), + m_match_all_users (false) + { + } + + ProcessInstanceInfoMatch (const char *process_name, + NameMatchType process_name_match_type) : + m_match_info (), + m_name_match_type (process_name_match_type), + m_match_all_users (false) + { + m_match_info.GetExecutableFile().SetFile(process_name, false); + } + + ProcessInstanceInfo & + GetProcessInfo () + { + return m_match_info; + } + + const ProcessInstanceInfo & + GetProcessInfo () const + { + return m_match_info; + } + + bool + GetMatchAllUsers () const + { + return m_match_all_users; + } + + void + SetMatchAllUsers (bool b) + { + m_match_all_users = b; + } + + NameMatchType + GetNameMatchType () const + { + return m_name_match_type; + } + + void + SetNameMatchType (NameMatchType name_match_type) + { + m_name_match_type = name_match_type; + } + + bool + NameMatches (const char *process_name) const; + + bool + Matches (const ProcessInstanceInfo &proc_info) const; + + bool + MatchAllProcesses () const; + void + Clear (); + +protected: + ProcessInstanceInfo m_match_info; + NameMatchType m_name_match_type; + bool m_match_all_users; +}; + +class ProcessInstanceInfoList +{ +public: + ProcessInstanceInfoList () : + m_infos() + { + } + + void + Clear() + { + m_infos.clear(); + } + + size_t + GetSize() + { + return m_infos.size(); + } + + void + Append (const ProcessInstanceInfo &info) + { + m_infos.push_back (info); + } + + const char * + GetProcessNameAtIndex (size_t idx) + { + if (idx < m_infos.size()) + return m_infos[idx].GetName(); + return NULL; + } + + size_t + GetProcessNameLengthAtIndex (size_t idx) + { + if (idx < m_infos.size()) + return m_infos[idx].GetNameLength(); + return 0; + } + + lldb::pid_t + GetProcessIDAtIndex (size_t idx) + { + if (idx < m_infos.size()) + return m_infos[idx].GetProcessID(); + return 0; + } + + bool + GetInfoAtIndex (size_t idx, ProcessInstanceInfo &info) + { + if (idx < m_infos.size()) + { + info = m_infos[idx]; + return true; + } + return false; + } + + // You must ensure "idx" is valid before calling this function + const ProcessInstanceInfo & + GetProcessInfoAtIndex (size_t idx) const + { + assert (idx < m_infos.size()); + return m_infos[idx]; + } + +protected: + typedef std::vector<ProcessInstanceInfo> collection; + collection m_infos; +}; + + +// This class tracks the Modification state of the process. Things that can currently modify +// the program are running the program (which will up the StopID) and writing memory (which +// will up the MemoryID.) +// FIXME: Should we also include modification of register states? + +class ProcessModID +{ +friend bool operator== (const ProcessModID &lhs, const ProcessModID &rhs); +public: + ProcessModID () : + m_stop_id (0), + m_last_natural_stop_id(0), + m_resume_id (0), + m_memory_id (0), + m_last_user_expression_resume (0), + m_running_user_expression (false) + {} + + ProcessModID (const ProcessModID &rhs) : + m_stop_id (rhs.m_stop_id), + m_memory_id (rhs.m_memory_id) + {} + + const ProcessModID & operator= (const ProcessModID &rhs) + { + if (this != &rhs) + { + m_stop_id = rhs.m_stop_id; + m_memory_id = rhs.m_memory_id; + } + return *this; + } + + ~ProcessModID () {} + + void BumpStopID () { + m_stop_id++; + if (!IsLastResumeForUserExpression()) + m_last_natural_stop_id++; + } + + void BumpMemoryID () { m_memory_id++; } + + void BumpResumeID () { + m_resume_id++; + if (m_running_user_expression > 0) + m_last_user_expression_resume = m_resume_id; + } + + uint32_t GetStopID() const { return m_stop_id; } + uint32_t GetLastNaturalStopID() const { return m_last_natural_stop_id; } + uint32_t GetMemoryID () const { return m_memory_id; } + uint32_t GetResumeID () const { return m_resume_id; } + uint32_t GetLastUserExpressionResumeID () const { return m_last_user_expression_resume; } + + bool MemoryIDEqual (const ProcessModID &compare) const + { + return m_memory_id == compare.m_memory_id; + } + + bool StopIDEqual (const ProcessModID &compare) const + { + return m_stop_id == compare.m_stop_id; + } + + void SetInvalid () + { + m_stop_id = UINT32_MAX; + } + + bool IsValid () const + { + return m_stop_id != UINT32_MAX; + } + + bool + IsLastResumeForUserExpression () const + { + return m_resume_id == m_last_user_expression_resume; + } + + void + SetRunningUserExpression (bool on) + { + // REMOVEME printf ("Setting running user expression %s at resume id %d - value: %d.\n", on ? "on" : "off", m_resume_id, m_running_user_expression); + if (on) + m_running_user_expression++; + else + m_running_user_expression--; + } + +private: + uint32_t m_stop_id; + uint32_t m_last_natural_stop_id; + uint32_t m_resume_id; + uint32_t m_memory_id; + uint32_t m_last_user_expression_resume; + uint32_t m_running_user_expression; +}; +inline bool operator== (const ProcessModID &lhs, const ProcessModID &rhs) +{ + if (lhs.StopIDEqual (rhs) + && lhs.MemoryIDEqual (rhs)) + return true; + else + return false; +} + +inline bool operator!= (const ProcessModID &lhs, const ProcessModID &rhs) +{ + if (!lhs.StopIDEqual (rhs) + || !lhs.MemoryIDEqual (rhs)) + return true; + else + return false; +} + +class MemoryRegionInfo +{ +public: + typedef Range<lldb::addr_t, lldb::addr_t> RangeType; + + enum OptionalBool { + eDontKnow = -1, + eNo = 0, + eYes = 1 + }; + + MemoryRegionInfo () : + m_range (), + m_read (eDontKnow), + m_write (eDontKnow), + m_execute (eDontKnow) + { + } + + ~MemoryRegionInfo () + { + } + + RangeType & + GetRange() + { + return m_range; + } + + void + Clear() + { + m_range.Clear(); + m_read = m_write = m_execute = eDontKnow; + } + + const RangeType & + GetRange() const + { + return m_range; + } + + OptionalBool + GetReadable () const + { + return m_read; + } + + OptionalBool + GetWritable () const + { + return m_write; + } + + OptionalBool + GetExecutable () const + { + return m_execute; + } + + void + SetReadable (OptionalBool val) + { + m_read = val; + } + + void + SetWritable (OptionalBool val) + { + m_write = val; + } + + void + SetExecutable (OptionalBool val) + { + m_execute = val; + } + +protected: + RangeType m_range; + OptionalBool m_read; + OptionalBool m_write; + OptionalBool m_execute; +}; + +//---------------------------------------------------------------------- +/// @class Process Process.h "lldb/Target/Process.h" +/// @brief A plug-in interface definition class for debugging a process. +//---------------------------------------------------------------------- +class Process : + public std::enable_shared_from_this<Process>, + public ProcessProperties, + public UserID, + public Broadcaster, + public ExecutionContextScope, + public PluginInterface +{ +friend class ThreadList; +friend class ClangFunction; // For WaitForStateChangeEventsPrivate +friend class CommandObjectProcessLaunch; +friend class ProcessEventData; +friend class CommandObjectBreakpointCommand; +friend class StopInfo; + +public: + + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + enum + { + eBroadcastBitStateChanged = (1 << 0), + eBroadcastBitInterrupt = (1 << 1), + eBroadcastBitSTDOUT = (1 << 2), + eBroadcastBitSTDERR = (1 << 3), + eBroadcastBitProfileData = (1 << 4) + }; + + enum + { + eBroadcastInternalStateControlStop = (1<<0), + eBroadcastInternalStateControlPause = (1<<1), + eBroadcastInternalStateControlResume = (1<<2) + }; + + typedef Range<lldb::addr_t, lldb::addr_t> LoadRange; + // We use a read/write lock to allow on or more clients to + // access the process state while the process is stopped (reader). + // We lock the write lock to control access to the process + // while it is running (readers, or clients that want the process + // stopped can block waiting for the process to stop, or just + // try to lock it to see if they can immediately access the stopped + // process. If the try read lock fails, then the process is running. + typedef ProcessRunLock::ProcessRunLocker StopLocker; + + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + + + //------------------------------------------------------------------ + /// A notification structure that can be used by clients to listen + /// for changes in a process's lifetime. + /// + /// @see RegisterNotificationCallbacks (const Notifications&) + /// @see UnregisterNotificationCallbacks (const Notifications&) + //------------------------------------------------------------------ +#ifndef SWIG + typedef struct + { + void *baton; + void (*initialize)(void *baton, Process *process); + void (*process_state_changed) (void *baton, Process *process, lldb::StateType state); + } Notifications; + + class ProcessEventData : + public EventData + { + friend class Process; + + public: + ProcessEventData (); + ProcessEventData (const lldb::ProcessSP &process, lldb::StateType state); + + virtual ~ProcessEventData(); + + static const ConstString & + GetFlavorString (); + + virtual const ConstString & + GetFlavor () const; + + const lldb::ProcessSP & + GetProcessSP() const + { + return m_process_sp; + } + lldb::StateType + GetState() const + { + return m_state; + } + bool + GetRestarted () const + { + return m_restarted; + } + + size_t + GetNumRestartedReasons () + { + return m_restarted_reasons.size(); + } + + const char * + GetRestartedReasonAtIndex(size_t idx) + { + if (idx > m_restarted_reasons.size()) + return NULL; + else + return m_restarted_reasons[idx].c_str(); + } + + bool + GetInterrupted () const + { + return m_interrupted; + } + + virtual void + Dump (Stream *s) const; + + virtual void + DoOnRemoval (Event *event_ptr); + + static const Process::ProcessEventData * + GetEventDataFromEvent (const Event *event_ptr); + + static lldb::ProcessSP + GetProcessFromEvent (const Event *event_ptr); + + static lldb::StateType + GetStateFromEvent (const Event *event_ptr); + + static bool + GetRestartedFromEvent (const Event *event_ptr); + + static size_t + GetNumRestartedReasons(const Event *event_ptr); + + static const char * + GetRestartedReasonAtIndex(const Event *event_ptr, size_t idx); + + static void + AddRestartedReason (Event *event_ptr, const char *reason); + + static void + SetRestartedInEvent (Event *event_ptr, bool new_value); + + static bool + GetInterruptedFromEvent (const Event *event_ptr); + + static void + SetInterruptedInEvent (Event *event_ptr, bool new_value); + + static bool + SetUpdateStateOnRemoval (Event *event_ptr); + + private: + + void + SetUpdateStateOnRemoval() + { + m_update_state++; + } + void + SetRestarted (bool new_value) + { + m_restarted = new_value; + } + void + SetInterrupted (bool new_value) + { + m_interrupted = new_value; + } + void + AddRestartedReason (const char *reason) + { + m_restarted_reasons.push_back(reason); + } + + lldb::ProcessSP m_process_sp; + lldb::StateType m_state; + std::vector<std::string> m_restarted_reasons; + bool m_restarted; // For "eStateStopped" events, this is true if the target was automatically restarted. + int m_update_state; + bool m_interrupted; + DISALLOW_COPY_AND_ASSIGN (ProcessEventData); + + }; + +#endif + + static void + SettingsInitialize (); + + static void + SettingsTerminate (); + + static const ProcessPropertiesSP & + GetGlobalProperties(); + + //------------------------------------------------------------------ + /// Construct with a shared pointer to a target, and the Process listener. + //------------------------------------------------------------------ + Process(Target &target, Listener &listener); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~Process(); + + //------------------------------------------------------------------ + /// Find a Process plug-in that can debug \a module using the + /// currently selected architecture. + /// + /// Scans all loaded plug-in interfaces that implement versions of + /// the Process plug-in interface and returns the first instance + /// that can debug the file. + /// + /// @param[in] module_sp + /// The module shared pointer that this process will debug. + /// + /// @param[in] plugin_name + /// If NULL, select the best plug-in for the binary. If non-NULL + /// then look for a plugin whose PluginInfo's name matches + /// this string. + /// + /// @see Process::CanDebug () + //------------------------------------------------------------------ + static lldb::ProcessSP + FindPlugin (Target &target, + const char *plugin_name, + Listener &listener, + const FileSpec *crash_file_path); + + + + //------------------------------------------------------------------ + /// Static function that can be used with the \b host function + /// Host::StartMonitoringChildProcess (). + /// + /// This function can be used by lldb_private::Process subclasses + /// when they want to watch for a local process and have its exit + /// status automatically set when the host child process exits. + /// Subclasses should call Host::StartMonitoringChildProcess () + /// with: + /// callback = Process::SetHostProcessExitStatus + /// callback_baton = NULL + /// pid = Process::GetID() + /// monitor_signals = false + //------------------------------------------------------------------ + static bool + SetProcessExitStatus (void *callback_baton, // The callback baton which should be set to NULL + lldb::pid_t pid, // The process ID we want to monitor + bool exited, + int signo, // Zero for no signal + int status); // Exit value of process if signal is zero + + lldb::ByteOrder + GetByteOrder () const; + + uint32_t + GetAddressByteSize () const; + + uint32_t + GetUniqueID() const + { + return m_process_unique_id; + } + //------------------------------------------------------------------ + /// Check if a plug-in instance can debug the file in \a module. + /// + /// Each plug-in is given a chance to say whether it can debug + /// the file in \a module. If the Process plug-in instance can + /// debug a file on the current system, it should return \b true. + /// + /// @return + /// Returns \b true if this Process plug-in instance can + /// debug the executable, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + CanDebug (Target &target, + bool plugin_specified_by_name) = 0; + + + //------------------------------------------------------------------ + /// This object is about to be destroyed, do any necessary cleanup. + /// + /// Subclasses that override this method should always call this + /// superclass method. + //------------------------------------------------------------------ + virtual void + Finalize(); + + + //------------------------------------------------------------------ + /// Return whether this object is valid (i.e. has not been finalized.) + /// + /// @return + /// Returns \b true if this Process has not been finalized + /// and \b false otherwise. + //------------------------------------------------------------------ + bool + IsValid() const + { + return !m_finalize_called; + } + + //------------------------------------------------------------------ + /// Return a multi-word command object that can be used to expose + /// plug-in specific commands. + /// + /// This object will be used to resolve plug-in commands and can be + /// triggered by a call to: + /// + /// (lldb) process commmand <args> + /// + /// @return + /// A CommandObject which can be one of the concrete subclasses + /// of CommandObject like CommandObjectRaw, CommandObjectParsed, + /// or CommandObjectMultiword. + //------------------------------------------------------------------ + virtual CommandObject * + GetPluginCommandObject() + { + return NULL; + } + + //------------------------------------------------------------------ + /// Launch a new process. + /// + /// Launch a new process by spawning a new process using the + /// target object's executable module's file as the file to launch. + /// Arguments are given in \a argv, and the environment variables + /// are in \a envp. Standard input and output files can be + /// optionally re-directed to \a stdin_path, \a stdout_path, and + /// \a stderr_path. + /// + /// This function is not meant to be overridden by Process + /// subclasses. It will first call Process::WillLaunch (Module *) + /// and if that returns \b true, Process::DoLaunch (Module*, + /// char const *[],char const *[],const char *,const char *, + /// const char *) will be called to actually do the launching. If + /// DoLaunch returns \b true, then Process::DidLaunch() will be + /// called. + /// + /// @param[in] argv + /// The argument array. + /// + /// @param[in] envp + /// The environment array. + /// + /// @param[in] launch_flags + /// Flags to modify the launch (@see lldb::LaunchFlags) + /// + /// @param[in] stdin_path + /// The path to use when re-directing the STDIN of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stdout_path + /// The path to use when re-directing the STDOUT of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stderr_path + /// The path to use when re-directing the STDERR of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] working_directory + /// The working directory to have the child process run in + /// + /// @return + /// An error object. Call GetID() to get the process ID if + /// the error object is success. + //------------------------------------------------------------------ + virtual Error + Launch (const ProcessLaunchInfo &launch_info); + + virtual Error + LoadCore (); + + virtual Error + DoLoadCore () + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support loading core files.", GetPluginName().GetCString()); + return error; + } + + //------------------------------------------------------------------ + /// Get the dynamic loader plug-in for this process. + /// + /// The default action is to let the DynamicLoader plug-ins check + /// the main executable and the DynamicLoader will select itself + /// automatically. Subclasses can override this if inspecting the + /// executable is not desired, or if Process subclasses can only + /// use a specific DynamicLoader plug-in. + //------------------------------------------------------------------ + virtual DynamicLoader * + GetDynamicLoader (); + + //------------------------------------------------------------------ + /// Attach to an existing process using the process attach info. + /// + /// This function is not meant to be overridden by Process + /// subclasses. It will first call WillAttach (lldb::pid_t) + /// or WillAttach (const char *), and if that returns \b + /// true, DoAttach (lldb::pid_t) or DoAttach (const char *) will + /// be called to actually do the attach. If DoAttach returns \b + /// true, then Process::DidAttach() will be called. + /// + /// @param[in] pid + /// The process ID that we should attempt to attach to. + /// + /// @return + /// Returns \a pid if attaching was successful, or + /// LLDB_INVALID_PROCESS_ID if attaching fails. + //------------------------------------------------------------------ + virtual Error + Attach (ProcessAttachInfo &attach_info); + + //------------------------------------------------------------------ + /// Attach to a remote system via a URL + /// + /// @param[in] strm + /// A stream where output intended for the user + /// (if the driver has a way to display that) generated during + /// the connection. This may be NULL if no output is needed.A + /// + /// @param[in] remote_url + /// The URL format that we are connecting to. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + ConnectRemote (Stream *strm, const char *remote_url); + + bool + GetShouldDetach () const + { + return m_should_detach; + } + + void + SetShouldDetach (bool b) + { + m_should_detach = b; + } + + //------------------------------------------------------------------ + /// Get the image information address for the current process. + /// + /// Some runtimes have system functions that can help dynamic + /// loaders locate the dynamic loader information needed to observe + /// shared libraries being loaded or unloaded. This function is + /// in the Process interface (as opposed to the DynamicLoader + /// interface) to ensure that remote debugging can take advantage of + /// this functionality. + /// + /// @return + /// The address of the dynamic loader information, or + /// LLDB_INVALID_ADDRESS if this is not supported by this + /// interface. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetImageInfoAddress (); + + //------------------------------------------------------------------ + /// Load a shared library into this process. + /// + /// Try and load a shared library into the current process. This + /// call might fail in the dynamic loader plug-in says it isn't safe + /// to try and load shared libraries at the moment. + /// + /// @param[in] image_spec + /// The image file spec that points to the shared library that + /// you want to load. + /// + /// @param[out] error + /// An error object that gets filled in with any errors that + /// might occur when trying to load the shared library. + /// + /// @return + /// A token that represents the shared library that can be + /// later used to unload the shared library. A value of + /// LLDB_INVALID_IMAGE_TOKEN will be returned if the shared + /// library can't be opened. + //------------------------------------------------------------------ + virtual uint32_t + LoadImage (const FileSpec &image_spec, Error &error); + + virtual Error + UnloadImage (uint32_t image_token); + + //------------------------------------------------------------------ + /// Register for process and thread notifications. + /// + /// Clients can register nofication callbacks by filling out a + /// Process::Notifications structure and calling this function. + /// + /// @param[in] callbacks + /// A structure that contains the notification baton and + /// callback functions. + /// + /// @see Process::Notifications + //------------------------------------------------------------------ +#ifndef SWIG + void + RegisterNotificationCallbacks (const Process::Notifications& callbacks); +#endif + //------------------------------------------------------------------ + /// Unregister for process and thread notifications. + /// + /// Clients can unregister nofication callbacks by passing a copy of + /// the original baton and callbacks in \a callbacks. + /// + /// @param[in] callbacks + /// A structure that contains the notification baton and + /// callback functions. + /// + /// @return + /// Returns \b true if the notification callbacks were + /// successfully removed from the process, \b false otherwise. + /// + /// @see Process::Notifications + //------------------------------------------------------------------ +#ifndef SWIG + bool + UnregisterNotificationCallbacks (const Process::Notifications& callbacks); +#endif + //================================================================== + // Built in Process Control functions + //================================================================== + //------------------------------------------------------------------ + /// Resumes all of a process's threads as configured using the + /// Thread run control functions. + /// + /// Threads for a process should be updated with one of the run + /// control actions (resume, step, or suspend) that they should take + /// when the process is resumed. If no run control action is given + /// to a thread it will be resumed by default. + /// + /// This function is not meant to be overridden by Process + /// subclasses. This function will take care of disabling any + /// breakpoints that threads may be stopped at, single stepping, and + /// re-enabling breakpoints, and enabling the basic flow control + /// that the plug-in instances need not worry about. + /// + /// N.B. This function also sets the Write side of the Run Lock, + /// which is unset when the corresponding stop event is pulled off + /// the Public Event Queue. If you need to resume the process without + /// setting the Run Lock, use PrivateResume (though you should only do + /// that from inside the Process class. + /// + /// @return + /// Returns an error object. + /// + /// @see Thread:Resume() + /// @see Thread:Step() + /// @see Thread:Suspend() + //------------------------------------------------------------------ + Error + Resume(); + + //------------------------------------------------------------------ + /// Halts a running process. + /// + /// This function is not meant to be overridden by Process + /// subclasses. + /// If the process is successfully halted, a eStateStopped + /// process event with GetInterrupted will be broadcast. If false, we will + /// halt the process with no events generated by the halt. + /// + /// @param[in] clear_thread_plans + /// If true, when the process stops, clear all thread plans. + /// + /// @return + /// Returns an error object. If the error is empty, the process is halted. + /// otherwise the halt has failed. + //------------------------------------------------------------------ + Error + Halt (bool clear_thread_plans = false); + + //------------------------------------------------------------------ + /// Detaches from a running or stopped process. + /// + /// This function is not meant to be overridden by Process + /// subclasses. + /// + /// @param[in] keep_stopped + /// If true, don't resume the process on detach. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + Error + Detach (bool keep_stopped); + + //------------------------------------------------------------------ + /// Kills the process and shuts down all threads that were spawned + /// to track and monitor the process. + /// + /// This function is not meant to be overridden by Process + /// subclasses. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + Error + Destroy(); + + //------------------------------------------------------------------ + /// Sends a process a UNIX signal \a signal. + /// + /// This function is not meant to be overridden by Process + /// subclasses. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + Error + Signal (int signal); + + virtual UnixSignals & + GetUnixSignals () + { + return m_unix_signals; + } + + //================================================================== + // Plug-in Process Control Overrides + //================================================================== + + //------------------------------------------------------------------ + /// Called before attaching to a process. + /// + /// Allow Process plug-ins to execute some code before attaching a + /// process. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + WillAttachToProcessWithID (lldb::pid_t pid) + { + return Error(); + } + + //------------------------------------------------------------------ + /// Called before attaching to a process. + /// + /// Allow Process plug-ins to execute some code before attaching a + /// process. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) + { + return Error(); + } + + //------------------------------------------------------------------ + /// Attach to a remote system via a URL + /// + /// @param[in] strm + /// A stream where output intended for the user + /// (if the driver has a way to display that) generated during + /// the connection. This may be NULL if no output is needed.A + /// + /// @param[in] remote_url + /// The URL format that we are connecting to. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + DoConnectRemote (Stream *strm, const char *remote_url) + { + Error error; + error.SetErrorString ("remote connections are not supported"); + return error; + } + + //------------------------------------------------------------------ + /// Attach to an existing process using a process ID. + /// + /// @param[in] pid + /// The process ID that we should attempt to attach to. + /// + /// @return + /// Returns \a pid if attaching was successful, or + /// LLDB_INVALID_PROCESS_ID if attaching fails. + //------------------------------------------------------------------ + virtual Error + DoAttachToProcessWithID (lldb::pid_t pid) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support attaching to a process by pid", GetPluginName().GetCString()); + return error; + } + + //------------------------------------------------------------------ + /// Attach to an existing process using a process ID. + /// + /// @param[in] pid + /// The process ID that we should attempt to attach to. + /// + /// @param[in] attach_info + /// Information on how to do the attach. For example, GetUserID() + /// will return the uid to attach as. + /// + /// @return + /// Returns \a pid if attaching was successful, or + /// LLDB_INVALID_PROCESS_ID if attaching fails. + /// hanming : need flag + //------------------------------------------------------------------ + virtual Error + DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support attaching to a process by pid", GetPluginName().GetCString()); + return error; + } + + //------------------------------------------------------------------ + /// Attach to an existing process using a partial process name. + /// + /// @param[in] process_name + /// The name of the process to attach to. + /// + /// @param[in] wait_for_launch + /// If \b true, wait for the process to be launched and attach + /// as soon as possible after it does launch. If \b false, then + /// search for a matching process the currently exists. + /// + /// @param[in] attach_info + /// Information on how to do the attach. For example, GetUserID() + /// will return the uid to attach as. + /// + /// @return + /// Returns \a pid if attaching was successful, or + /// LLDB_INVALID_PROCESS_ID if attaching fails. + //------------------------------------------------------------------ + virtual Error + DoAttachToProcessWithName (const char *process_name, bool wait_for_launch, const ProcessAttachInfo &attach_info) + { + Error error; + error.SetErrorString("attach by name is not supported"); + return error; + } + + //------------------------------------------------------------------ + /// Called after attaching a process. + /// + /// Allow Process plug-ins to execute some code after attaching to + /// a process. + //------------------------------------------------------------------ + virtual void + DidAttach () {} + + + //------------------------------------------------------------------ + /// Called after a process re-execs itself. + /// + /// Allow Process plug-ins to execute some code after a process has + /// exec'ed itself. Subclasses typically should override DoDidExec() + /// as the lldb_private::Process class needs to remove its dynamic + /// loader, runtime, ABI and other plug-ins, as well as unload all + /// shared libraries. + //------------------------------------------------------------------ + virtual void + DidExec (); + + //------------------------------------------------------------------ + /// Subclasses of Process should implement this function if they + /// need to do anything after a process exec's itself. + //------------------------------------------------------------------ + virtual void + DoDidExec () + { + } + + //------------------------------------------------------------------ + /// Called before launching to a process. + /// + /// Allow Process plug-ins to execute some code before launching a + /// process. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + WillLaunch (Module* module) + { + return Error(); + } + + //------------------------------------------------------------------ + /// Launch a new process. + /// + /// Launch a new process by spawning a new process using \a module's + /// file as the file to launch. Arguments are given in \a argv, + /// and the environment variables are in \a envp. Standard input + /// and output files can be optionally re-directed to \a stdin_path, + /// \a stdout_path, and \a stderr_path. + /// + /// @param[in] module + /// The module from which to extract the file specification and + /// launch. + /// + /// @param[in] argv + /// The argument array. + /// + /// @param[in] envp + /// The environment array. + /// + /// @param[in] launch_flags + /// Flags to modify the launch (@see lldb::LaunchFlags) + /// + /// @param[in] stdin_path + /// The path to use when re-directing the STDIN of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stdout_path + /// The path to use when re-directing the STDOUT of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] stderr_path + /// The path to use when re-directing the STDERR of the new + /// process. If all stdXX_path arguments are NULL, a pseudo + /// terminal will be used. + /// + /// @param[in] working_directory + /// The working directory to have the child process run in + /// + /// @return + /// A new valid process ID, or LLDB_INVALID_PROCESS_ID if + /// launching fails. + //------------------------------------------------------------------ + virtual Error + DoLaunch (Module *exe_module, + const ProcessLaunchInfo &launch_info) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support launching processes", GetPluginName().GetCString()); + return error; + } + + + //------------------------------------------------------------------ + /// Called after launching a process. + /// + /// Allow Process plug-ins to execute some code after launching + /// a process. + //------------------------------------------------------------------ + virtual void + DidLaunch () {} + + + + //------------------------------------------------------------------ + /// Called before resuming to a process. + /// + /// Allow Process plug-ins to execute some code before resuming a + /// process. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + WillResume () { return Error(); } + + //------------------------------------------------------------------ + /// Resumes all of a process's threads as configured using the + /// Thread run control functions. + /// + /// Threads for a process should be updated with one of the run + /// control actions (resume, step, or suspend) that they should take + /// when the process is resumed. If no run control action is given + /// to a thread it will be resumed by default. + /// + /// @return + /// Returns \b true if the process successfully resumes using + /// the thread run control actions, \b false otherwise. + /// + /// @see Thread:Resume() + /// @see Thread:Step() + /// @see Thread:Suspend() + //------------------------------------------------------------------ + virtual Error + DoResume () + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support resuming processes", GetPluginName().GetCString()); + return error; + } + + + //------------------------------------------------------------------ + /// Called after resuming a process. + /// + /// Allow Process plug-ins to execute some code after resuming + /// a process. + //------------------------------------------------------------------ + virtual void + DidResume () {} + + + //------------------------------------------------------------------ + /// Called before halting to a process. + /// + /// Allow Process plug-ins to execute some code before halting a + /// process. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + WillHalt () { return Error(); } + + //------------------------------------------------------------------ + /// Halts a running process. + /// + /// DoHalt must produce one and only one stop StateChanged event if it actually + /// stops the process. If the stop happens through some natural event (for + /// instance a SIGSTOP), then forwarding that event will do. Otherwise, you must + /// generate the event manually. Note also, the private event thread is stopped when + /// DoHalt is run to prevent the events generated while halting to trigger + /// other state changes before the halt is complete. + /// + /// @param[out] caused_stop + /// If true, then this Halt caused the stop, otherwise, the + /// process was already stopped. + /// + /// @return + /// Returns \b true if the process successfully halts, \b false + /// otherwise. + //------------------------------------------------------------------ + virtual Error + DoHalt (bool &caused_stop) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support halting processes", GetPluginName().GetCString()); + return error; + } + + + //------------------------------------------------------------------ + /// Called after halting a process. + /// + /// Allow Process plug-ins to execute some code after halting + /// a process. + //------------------------------------------------------------------ + virtual void + DidHalt () {} + + //------------------------------------------------------------------ + /// Called before detaching from a process. + /// + /// Allow Process plug-ins to execute some code before detaching + /// from a process. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + WillDetach () + { + return Error(); + } + + //------------------------------------------------------------------ + /// Detaches from a running or stopped process. + /// + /// @return + /// Returns \b true if the process successfully detaches, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual Error + DoDetach (bool keep_stopped) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support detaching from processes", GetPluginName().GetCString()); + return error; + } + + + //------------------------------------------------------------------ + /// Called after detaching from a process. + /// + /// Allow Process plug-ins to execute some code after detaching + /// from a process. + //------------------------------------------------------------------ + virtual void + DidDetach () {} + + virtual bool + DetachRequiresHalt() { return false; } + + //------------------------------------------------------------------ + /// Called before sending a signal to a process. + /// + /// Allow Process plug-ins to execute some code before sending a + /// signal to a process. + /// + /// @return + /// Returns no error if it is safe to proceed with a call to + /// Process::DoSignal(int), otherwise an error describing what + /// prevents the signal from being sent. + //------------------------------------------------------------------ + virtual Error + WillSignal () { return Error(); } + + //------------------------------------------------------------------ + /// Sends a process a UNIX signal \a signal. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + DoSignal (int signal) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support senging signals to processes", GetPluginName().GetCString()); + return error; + } + + virtual Error + WillDestroy () { return Error(); } + + virtual Error + DoDestroy () = 0; + + virtual void + DidDestroy () { } + + virtual bool + DestroyRequiresHalt() { return true; } + + + //------------------------------------------------------------------ + /// Called after sending a signal to a process. + /// + /// Allow Process plug-ins to execute some code after sending a + /// signal to a process. + //------------------------------------------------------------------ + virtual void + DidSignal () {} + + //------------------------------------------------------------------ + /// Currently called as part of ShouldStop. + /// FIXME: Should really happen when the target stops before the + /// event is taken from the queue... + /// + /// This callback is called as the event + /// is about to be queued up to allow Process plug-ins to execute + /// some code prior to clients being notified that a process was + /// stopped. Common operations include updating the thread list, + /// invalidating any thread state (registers, stack, etc) prior to + /// letting the notification go out. + /// + //------------------------------------------------------------------ + virtual void + RefreshStateAfterStop () = 0; + + //------------------------------------------------------------------ + /// Get the target object pointer for this module. + /// + /// @return + /// A Target object pointer to the target that owns this + /// module. + //------------------------------------------------------------------ + Target & + GetTarget () + { + return m_target; + } + + //------------------------------------------------------------------ + /// Get the const target object pointer for this module. + /// + /// @return + /// A const Target object pointer to the target that owns this + /// module. + //------------------------------------------------------------------ + const Target & + GetTarget () const + { + return m_target; + } + + //------------------------------------------------------------------ + /// Flush all data in the process. + /// + /// Flush the memory caches, all threads, and any other cached data + /// in the process. + /// + /// This function can be called after a world changing event like + /// adding a new symbol file, or after the process makes a large + /// context switch (from boot ROM to booted into an OS). + //------------------------------------------------------------------ + void + Flush (); + + //------------------------------------------------------------------ + /// Get accessor for the current process state. + /// + /// @return + /// The current state of the process. + /// + /// @see lldb::StateType + //------------------------------------------------------------------ + lldb::StateType + GetState (); + + ExecutionResults + RunThreadPlan (ExecutionContext &exe_ctx, + lldb::ThreadPlanSP &thread_plan_sp, + bool stop_others, + bool run_others, + bool unwind_on_error, + bool ignore_breakpoints, + uint32_t timeout_usec, + Stream &errors); + + static const char * + ExecutionResultAsCString (ExecutionResults result); + + void + GetStatus (Stream &ostrm); + + size_t + GetThreadStatus (Stream &ostrm, + bool only_threads_with_stop_reason, + uint32_t start_frame, + uint32_t num_frames, + uint32_t num_frames_with_source); + + void + SendAsyncInterrupt (); + +protected: + + void + SetState (lldb::EventSP &event_sp); + + lldb::StateType + GetPrivateState (); + + //------------------------------------------------------------------ + /// The "private" side of resuming a process. This doesn't alter the + /// state of m_run_lock, but just causes the process to resume. + /// + /// @return + /// An Error object describing the success or failure of the resume. + //------------------------------------------------------------------ + Error + PrivateResume (); + + //------------------------------------------------------------------ + // Called internally + //------------------------------------------------------------------ + void + CompleteAttach (); + +public: + //------------------------------------------------------------------ + /// Get the exit status for a process. + /// + /// @return + /// The process's return code, or -1 if the current process + /// state is not eStateExited. + //------------------------------------------------------------------ + int + GetExitStatus (); + + //------------------------------------------------------------------ + /// Get a textual description of what the process exited. + /// + /// @return + /// The textual description of why the process exited, or NULL + /// if there is no description available. + //------------------------------------------------------------------ + const char * + GetExitDescription (); + + + virtual void + DidExit () + { + } + + //------------------------------------------------------------------ + /// Get the Modification ID of the process. + /// + /// @return + /// The modification ID of the process. + //------------------------------------------------------------------ + ProcessModID + GetModID () const + { + return m_mod_id; + } + + const ProcessModID & + GetModIDRef () const + { + return m_mod_id; + } + + uint32_t + GetStopID () const + { + return m_mod_id.GetStopID(); + } + + uint32_t + GetResumeID () const + { + return m_mod_id.GetResumeID(); + } + + uint32_t + GetLastUserExpressionResumeID () const + { + return m_mod_id.GetLastUserExpressionResumeID(); + } + + uint32_t + GetLastNaturalStopID() + { + return m_mod_id.GetLastNaturalStopID(); + } + + //------------------------------------------------------------------ + /// Set accessor for the process exit status (return code). + /// + /// Sometimes a child exits and the exit can be detected by global + /// functions (signal handler for SIGCHLD for example). This + /// accessor allows the exit status to be set from an external + /// source. + /// + /// Setting this will cause a eStateExited event to be posted to + /// the process event queue. + /// + /// @param[in] exit_status + /// The value for the process's return code. + /// + /// @see lldb::StateType + //------------------------------------------------------------------ + virtual bool + SetExitStatus (int exit_status, const char *cstr); + + //------------------------------------------------------------------ + /// Check if a process is still alive. + /// + /// @return + /// Returns \b true if the process is still valid, \b false + /// otherwise. + //------------------------------------------------------------------ + virtual bool + IsAlive () = 0; + + //------------------------------------------------------------------ + /// Before lldb detaches from a process, it warns the user that they are about to lose their debug session. + /// In some cases, this warning doesn't need to be emitted -- for instance, with core file debugging where + /// the user can reconstruct the "state" by simply re-running the debugger on the core file. + /// + /// @return + // true if the user should be warned about detaching from this process. + //------------------------------------------------------------------ + virtual bool + WarnBeforeDetach () const + { + return true; + } + + //------------------------------------------------------------------ + /// Actually do the reading of memory from a process. + /// + /// Subclasses must override this function and can return fewer + /// bytes than requested when memory requests are too large. This + /// class will break up the memory requests and keep advancing the + /// arguments along as needed. + /// + /// @param[in] vm_addr + /// A virtual load address that indicates where to start reading + /// memory from. + /// + /// @param[in] size + /// The number of bytes to read. + /// + /// @param[out] buf + /// A byte buffer that is at least \a size bytes long that + /// will receive the memory bytes. + /// + /// @return + /// The number of bytes that were actually read into \a buf. + //------------------------------------------------------------------ + virtual size_t + DoReadMemory (lldb::addr_t vm_addr, + void *buf, + size_t size, + Error &error) = 0; + + //------------------------------------------------------------------ + /// Read of memory from a process. + /// + /// This function will read memory from the current process's + /// address space and remove any traps that may have been inserted + /// into the memory. + /// + /// This function is not meant to be overridden by Process + /// subclasses, the subclasses should implement + /// Process::DoReadMemory (lldb::addr_t, size_t, void *). + /// + /// @param[in] vm_addr + /// A virtual load address that indicates where to start reading + /// memory from. + /// + /// @param[out] buf + /// A byte buffer that is at least \a size bytes long that + /// will receive the memory bytes. + /// + /// @param[in] size + /// The number of bytes to read. + /// + /// @return + /// The number of bytes that were actually read into \a buf. If + /// the returned number is greater than zero, yet less than \a + /// size, then this function will get called again with \a + /// vm_addr, \a buf, and \a size updated appropriately. Zero is + /// returned to indicate an error. + //------------------------------------------------------------------ + virtual size_t + ReadMemory (lldb::addr_t vm_addr, + void *buf, + size_t size, + Error &error); + + //------------------------------------------------------------------ + /// Read a NULL terminated string from memory + /// + /// This function will read a cache page at a time until a NULL + /// string terminator is found. It will stop reading if an aligned + /// sequence of NULL termination \a type_width bytes is not found + /// before reading \a cstr_max_len bytes. The results are always + /// guaranteed to be NULL terminated, and that no more than + /// (max_bytes - type_width) bytes will be read. + /// + /// @param[in] vm_addr + /// The virtual load address to start the memory read. + /// + /// @param[in] str + /// A character buffer containing at least max_bytes. + /// + /// @param[in] max_bytes + /// The maximum number of bytes to read. + /// + /// @param[in] error + /// The error status of the read operation. + /// + /// @param[in] type_width + /// The size of the null terminator (1 to 4 bytes per + /// character). Defaults to 1. + /// + /// @return + /// The error status or the number of bytes prior to the null terminator. + //------------------------------------------------------------------ + size_t + ReadStringFromMemory (lldb::addr_t vm_addr, + char *str, + size_t max_bytes, + Error &error, + size_t type_width = 1); + + //------------------------------------------------------------------ + /// Read a NULL terminated C string from memory + /// + /// This function will read a cache page at a time until the NULL + /// C string terminator is found. It will stop reading if the NULL + /// termination byte isn't found before reading \a cstr_max_len + /// bytes, and the results are always guaranteed to be NULL + /// terminated (at most cstr_max_len - 1 bytes will be read). + //------------------------------------------------------------------ + size_t + ReadCStringFromMemory (lldb::addr_t vm_addr, + char *cstr, + size_t cstr_max_len, + Error &error); + + size_t + ReadCStringFromMemory (lldb::addr_t vm_addr, + std::string &out_str, + Error &error); + + size_t + ReadMemoryFromInferior (lldb::addr_t vm_addr, + void *buf, + size_t size, + Error &error); + + //------------------------------------------------------------------ + /// Reads an unsigned integer of the specified byte size from + /// process memory. + /// + /// @param[in] load_addr + /// A load address of the integer to read. + /// + /// @param[in] byte_size + /// The size in byte of the integer to read. + /// + /// @param[in] fail_value + /// The value to return if we fail to read an integer. + /// + /// @param[out] error + /// An error that indicates the success or failure of this + /// operation. If error indicates success (error.Success()), + /// then the value returned can be trusted, otherwise zero + /// will be returned. + /// + /// @return + /// The unsigned integer that was read from the process memory + /// space. If the integer was smaller than a uint64_t, any + /// unused upper bytes will be zero filled. If the process + /// byte order differs from the host byte order, the integer + /// value will be appropriately byte swapped into host byte + /// order. + //------------------------------------------------------------------ + uint64_t + ReadUnsignedIntegerFromMemory (lldb::addr_t load_addr, + size_t byte_size, + uint64_t fail_value, + Error &error); + + lldb::addr_t + ReadPointerFromMemory (lldb::addr_t vm_addr, + Error &error); + + bool + WritePointerToMemory (lldb::addr_t vm_addr, + lldb::addr_t ptr_value, + Error &error); + + //------------------------------------------------------------------ + /// Actually do the writing of memory to a process. + /// + /// @param[in] vm_addr + /// A virtual load address that indicates where to start writing + /// memory to. + /// + /// @param[in] buf + /// A byte buffer that is at least \a size bytes long that + /// contains the data to write. + /// + /// @param[in] size + /// The number of bytes to write. + /// + /// @param[out] error + /// An error value in case the memory write fails. + /// + /// @return + /// The number of bytes that were actually written. + //------------------------------------------------------------------ + virtual size_t + DoWriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error) + { + error.SetErrorStringWithFormat("error: %s does not support writing to processes", GetPluginName().GetCString()); + return 0; + } + + + //------------------------------------------------------------------ + /// Write all or part of a scalar value to memory. + /// + /// The value contained in \a scalar will be swapped to match the + /// byte order of the process that is being debugged. If \a size is + /// less than the size of scalar, the least significate \a size bytes + /// from scalar will be written. If \a size is larger than the byte + /// size of scalar, then the extra space will be padded with zeros + /// and the scalar value will be placed in the least significant + /// bytes in memory. + /// + /// @param[in] vm_addr + /// A virtual load address that indicates where to start writing + /// memory to. + /// + /// @param[in] scalar + /// The scalar to write to the debugged process. + /// + /// @param[in] size + /// This value can be smaller or larger than the scalar value + /// itself. If \a size is smaller than the size of \a scalar, + /// the least significant bytes in \a scalar will be used. If + /// \a size is larger than the byte size of \a scalar, then + /// the extra space will be padded with zeros. If \a size is + /// set to UINT32_MAX, then the size of \a scalar will be used. + /// + /// @param[out] error + /// An error value in case the memory write fails. + /// + /// @return + /// The number of bytes that were actually written. + //------------------------------------------------------------------ + size_t + WriteScalarToMemory (lldb::addr_t vm_addr, + const Scalar &scalar, + size_t size, + Error &error); + + size_t + ReadScalarIntegerFromMemory (lldb::addr_t addr, + uint32_t byte_size, + bool is_signed, + Scalar &scalar, + Error &error); + + //------------------------------------------------------------------ + /// Write memory to a process. + /// + /// This function will write memory to the current process's + /// address space and maintain any traps that might be present due + /// to software breakpoints. + /// + /// This function is not meant to be overridden by Process + /// subclasses, the subclasses should implement + /// Process::DoWriteMemory (lldb::addr_t, size_t, void *). + /// + /// @param[in] vm_addr + /// A virtual load address that indicates where to start writing + /// memory to. + /// + /// @param[in] buf + /// A byte buffer that is at least \a size bytes long that + /// contains the data to write. + /// + /// @param[in] size + /// The number of bytes to write. + /// + /// @return + /// The number of bytes that were actually written. + //------------------------------------------------------------------ + size_t + WriteMemory (lldb::addr_t vm_addr, const void *buf, size_t size, Error &error); + + + //------------------------------------------------------------------ + /// Actually allocate memory in the process. + /// + /// This function will allocate memory in the process's address + /// space. This can't rely on the generic function calling mechanism, + /// since that requires this function. + /// + /// @param[in] size + /// The size of the allocation requested. + /// + /// @return + /// The address of the allocated buffer in the process, or + /// LLDB_INVALID_ADDRESS if the allocation failed. + //------------------------------------------------------------------ + + virtual lldb::addr_t + DoAllocateMemory (size_t size, uint32_t permissions, Error &error) + { + error.SetErrorStringWithFormat("error: %s does not support allocating in the debug process", GetPluginName().GetCString()); + return LLDB_INVALID_ADDRESS; + } + + + //------------------------------------------------------------------ + /// The public interface to allocating memory in the process. + /// + /// This function will allocate memory in the process's address + /// space. This can't rely on the generic function calling mechanism, + /// since that requires this function. + /// + /// @param[in] size + /// The size of the allocation requested. + /// + /// @param[in] permissions + /// Or together any of the lldb::Permissions bits. The permissions on + /// a given memory allocation can't be changed after allocation. Note + /// that a block that isn't set writable can still be written on from lldb, + /// just not by the process itself. + /// + /// @param[in/out] error + /// An error object to fill in if things go wrong. + /// @return + /// The address of the allocated buffer in the process, or + /// LLDB_INVALID_ADDRESS if the allocation failed. + //------------------------------------------------------------------ + + lldb::addr_t + AllocateMemory (size_t size, uint32_t permissions, Error &error); + + + //------------------------------------------------------------------ + /// Resolve dynamically loaded indirect functions. + /// + /// @param[in] address + /// The load address of the indirect function to resolve. + /// + /// @param[out] error + /// An error value in case the resolve fails. + /// + /// @return + /// The address of the resolved function. + /// LLDB_INVALID_ADDRESS if the resolution failed. + //------------------------------------------------------------------ + + virtual lldb::addr_t + ResolveIndirectFunction(const Address *address, Error &error) + { + error.SetErrorStringWithFormat("error: %s does not support indirect functions in the debug process", GetPluginName().GetCString()); + return LLDB_INVALID_ADDRESS; + } + + virtual Error + GetMemoryRegionInfo (lldb::addr_t load_addr, + MemoryRegionInfo &range_info) + { + Error error; + error.SetErrorString ("Process::GetMemoryRegionInfo() not supported"); + return error; + } + + virtual Error + GetWatchpointSupportInfo (uint32_t &num) + { + Error error; + num = 0; + error.SetErrorString ("Process::GetWatchpointSupportInfo() not supported"); + return error; + } + + virtual Error + GetWatchpointSupportInfo (uint32_t &num, bool& after) + { + Error error; + num = 0; + after = true; + error.SetErrorString ("Process::GetWatchpointSupportInfo() not supported"); + return error; + } + + lldb::ModuleSP + ReadModuleFromMemory (const FileSpec& file_spec, + lldb::addr_t header_addr); + + //------------------------------------------------------------------ + /// Attempt to get the attributes for a region of memory in the process. + /// + /// It may be possible for the remote debug server to inspect attributes + /// for a region of memory in the process, such as whether there is a + /// valid page of memory at a given address or whether that page is + /// readable/writable/executable by the process. + /// + /// @param[in] load_addr + /// The address of interest in the process. + /// + /// @param[out] permissions + /// If this call returns successfully, this bitmask will have + /// its Permissions bits set to indicate whether the region is + /// readable/writable/executable. If this call fails, the + /// bitmask values are undefined. + /// + /// @return + /// Returns true if it was able to determine the attributes of the + /// memory region. False if not. + //------------------------------------------------------------------ + + virtual bool + GetLoadAddressPermissions (lldb::addr_t load_addr, uint32_t &permissions) + { + MemoryRegionInfo range_info; + permissions = 0; + Error error (GetMemoryRegionInfo (load_addr, range_info)); + if (!error.Success()) + return false; + if (range_info.GetReadable() == MemoryRegionInfo::eDontKnow + || range_info.GetWritable() == MemoryRegionInfo::eDontKnow + || range_info.GetExecutable() == MemoryRegionInfo::eDontKnow) + { + return false; + } + + if (range_info.GetReadable() == MemoryRegionInfo::eYes) + permissions |= lldb::ePermissionsReadable; + + if (range_info.GetWritable() == MemoryRegionInfo::eYes) + permissions |= lldb::ePermissionsWritable; + + if (range_info.GetExecutable() == MemoryRegionInfo::eYes) + permissions |= lldb::ePermissionsExecutable; + + return true; + } + + //------------------------------------------------------------------ + /// Determines whether executing JIT-compiled code in this process + /// is possible. + /// + /// @return + /// True if execution of JIT code is possible; false otherwise. + //------------------------------------------------------------------ + bool CanJIT (); + + //------------------------------------------------------------------ + /// Sets whether executing JIT-compiled code in this process + /// is possible. + /// + /// @param[in] can_jit + /// True if execution of JIT code is possible; false otherwise. + //------------------------------------------------------------------ + void SetCanJIT (bool can_jit); + + //------------------------------------------------------------------ + /// Actually deallocate memory in the process. + /// + /// This function will deallocate memory in the process's address + /// space that was allocated with AllocateMemory. + /// + /// @param[in] ptr + /// A return value from AllocateMemory, pointing to the memory you + /// want to deallocate. + /// + /// @return + /// \btrue if the memory was deallocated, \bfalse otherwise. + //------------------------------------------------------------------ + + virtual Error + DoDeallocateMemory (lldb::addr_t ptr) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support deallocating in the debug process", GetPluginName().GetCString()); + return error; + } + + + //------------------------------------------------------------------ + /// The public interface to deallocating memory in the process. + /// + /// This function will deallocate memory in the process's address + /// space that was allocated with AllocateMemory. + /// + /// @param[in] ptr + /// A return value from AllocateMemory, pointing to the memory you + /// want to deallocate. + /// + /// @return + /// \btrue if the memory was deallocated, \bfalse otherwise. + //------------------------------------------------------------------ + + Error + DeallocateMemory (lldb::addr_t ptr); + + //------------------------------------------------------------------ + /// Get any available STDOUT. + /// + /// If the process was launched without supplying valid file paths + /// for stdin, stdout, and stderr, then the Process class might + /// try to cache the STDOUT for the process if it is able. Events + /// will be queued indicating that there is STDOUT available that + /// can be retrieved using this function. + /// + /// @param[out] buf + /// A buffer that will receive any STDOUT bytes that are + /// currently available. + /// + /// @param[out] buf_size + /// The size in bytes for the buffer \a buf. + /// + /// @return + /// The number of bytes written into \a buf. If this value is + /// equal to \a buf_size, another call to this function should + /// be made to retrieve more STDOUT data. + //------------------------------------------------------------------ + virtual size_t + GetSTDOUT (char *buf, size_t buf_size, Error &error); + + //------------------------------------------------------------------ + /// Get any available STDERR. + /// + /// If the process was launched without supplying valid file paths + /// for stdin, stdout, and stderr, then the Process class might + /// try to cache the STDERR for the process if it is able. Events + /// will be queued indicating that there is STDERR available that + /// can be retrieved using this function. + /// + /// @param[out] buf + /// A buffer that will receive any STDERR bytes that are + /// currently available. + /// + /// @param[out] buf_size + /// The size in bytes for the buffer \a buf. + /// + /// @return + /// The number of bytes written into \a buf. If this value is + /// equal to \a buf_size, another call to this function should + /// be made to retrieve more STDERR data. + //------------------------------------------------------------------ + virtual size_t + GetSTDERR (char *buf, size_t buf_size, Error &error); + + virtual size_t + PutSTDIN (const char *buf, size_t buf_size, Error &error) + { + error.SetErrorString("stdin unsupported"); + return 0; + } + + //------------------------------------------------------------------ + /// Get any available profile data. + /// + /// @param[out] buf + /// A buffer that will receive any profile data bytes that are + /// currently available. + /// + /// @param[out] buf_size + /// The size in bytes for the buffer \a buf. + /// + /// @return + /// The number of bytes written into \a buf. If this value is + /// equal to \a buf_size, another call to this function should + /// be made to retrieve more profile data. + //------------------------------------------------------------------ + virtual size_t + GetAsyncProfileData (char *buf, size_t buf_size, Error &error); + + //---------------------------------------------------------------------- + // Process Breakpoints + //---------------------------------------------------------------------- + size_t + GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site); + + virtual Error + EnableBreakpointSite (BreakpointSite *bp_site) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support enabling breakpoints", GetPluginName().GetCString()); + return error; + } + + + virtual Error + DisableBreakpointSite (BreakpointSite *bp_site) + { + Error error; + error.SetErrorStringWithFormat("error: %s does not support disabling breakpoints", GetPluginName().GetCString()); + return error; + } + + + // This is implemented completely using the lldb::Process API. Subclasses + // don't need to implement this function unless the standard flow of + // read existing opcode, write breakpoint opcode, verify breakpoint opcode + // doesn't work for a specific process plug-in. + virtual Error + EnableSoftwareBreakpoint (BreakpointSite *bp_site); + + // This is implemented completely using the lldb::Process API. Subclasses + // don't need to implement this function unless the standard flow of + // restoring original opcode in memory and verifying the restored opcode + // doesn't work for a specific process plug-in. + virtual Error + DisableSoftwareBreakpoint (BreakpointSite *bp_site); + + BreakpointSiteList & + GetBreakpointSiteList(); + + const BreakpointSiteList & + GetBreakpointSiteList() const; + + void + DisableAllBreakpointSites (); + + Error + ClearBreakpointSiteByID (lldb::user_id_t break_id); + + lldb::break_id_t + CreateBreakpointSite (const lldb::BreakpointLocationSP &owner, + bool use_hardware); + + Error + DisableBreakpointSiteByID (lldb::user_id_t break_id); + + Error + EnableBreakpointSiteByID (lldb::user_id_t break_id); + + + // BreakpointLocations use RemoveOwnerFromBreakpointSite to remove + // themselves from the owner's list of this breakpoint sites. + void + RemoveOwnerFromBreakpointSite (lldb::user_id_t owner_id, + lldb::user_id_t owner_loc_id, + lldb::BreakpointSiteSP &bp_site_sp); + + //---------------------------------------------------------------------- + // Process Watchpoints (optional) + //---------------------------------------------------------------------- + virtual Error + EnableWatchpoint (Watchpoint *wp, bool notify = true); + + virtual Error + DisableWatchpoint (Watchpoint *wp, bool notify = true); + + //------------------------------------------------------------------ + // Thread Queries + //------------------------------------------------------------------ + virtual bool + UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) = 0; + + void + UpdateThreadListIfNeeded (); + + ThreadList & + GetThreadList () + { + return m_thread_list; + } + + uint32_t + GetNextThreadIndexID (uint64_t thread_id); + + lldb::ThreadSP + CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context); + + // Returns true if an index id has been assigned to a thread. + bool + HasAssignedIndexIDToThread(uint64_t sb_thread_id); + + // Given a thread_id, it will assign a more reasonable index id for display to the user. + // If the thread_id has previously been assigned, the same index id will be used. + uint32_t + AssignIndexIDToThread(uint64_t thread_id); + + //------------------------------------------------------------------ + // Event Handling + //------------------------------------------------------------------ + lldb::StateType + GetNextEvent (lldb::EventSP &event_sp); + + lldb::StateType + WaitForProcessToStop (const TimeValue *timeout, lldb::EventSP *event_sp_ptr = NULL); + + lldb::StateType + WaitForStateChangedEvents (const TimeValue *timeout, lldb::EventSP &event_sp); + + Event * + PeekAtStateChangedEvents (); + + + class + ProcessEventHijacker + { + public: + ProcessEventHijacker (Process &process, Listener *listener) : + m_process (process) + { + m_process.HijackProcessEvents (listener); + } + ~ProcessEventHijacker () + { + m_process.RestoreProcessEvents(); + } + + private: + Process &m_process; + }; + friend class ProcessEventHijacker; + //------------------------------------------------------------------ + /// If you need to ensure that you and only you will hear about some public + /// event, then make a new listener, set to listen to process events, and + /// then call this with that listener. Then you will have to wait on that + /// listener explicitly for events (rather than using the GetNextEvent & WaitFor* + /// calls above. Be sure to call RestoreProcessEvents when you are done. + /// + /// @param[in] listener + /// This is the new listener to whom all process events will be delivered. + /// + /// @return + /// Returns \b true if the new listener could be installed, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + HijackProcessEvents (Listener *listener); + + //------------------------------------------------------------------ + /// Restores the process event broadcasting to its normal state. + /// + //------------------------------------------------------------------ + void + RestoreProcessEvents (); + +private: + //------------------------------------------------------------------ + /// This is the part of the event handling that for a process event. + /// It decides what to do with the event and returns true if the + /// event needs to be propagated to the user, and false otherwise. + /// If the event is not propagated, this call will most likely set + /// the target to executing again. + /// There is only one place where this call should be called, HandlePrivateEvent. + /// Don't call it from anywhere else... + /// + /// @param[in] event_ptr + /// This is the event we are handling. + /// + /// @return + /// Returns \b true if the event should be reported to the + /// user, \b false otherwise. + //------------------------------------------------------------------ + bool + ShouldBroadcastEvent (Event *event_ptr); + +public: + const lldb::ABISP & + GetABI (); + + OperatingSystem * + GetOperatingSystem () + { + return m_os_ap.get(); + } + + + virtual LanguageRuntime * + GetLanguageRuntime (lldb::LanguageType language, bool retry_if_null = true); + + virtual CPPLanguageRuntime * + GetCPPLanguageRuntime (bool retry_if_null = true); + + virtual ObjCLanguageRuntime * + GetObjCLanguageRuntime (bool retry_if_null = true); + + bool + IsPossibleDynamicValue (ValueObject& in_value); + + bool + IsRunning () const; + + DynamicCheckerFunctions *GetDynamicCheckers() + { + return m_dynamic_checkers_ap.get(); + } + + void SetDynamicCheckers(DynamicCheckerFunctions *dynamic_checkers) + { + m_dynamic_checkers_ap.reset(dynamic_checkers); + } + + //------------------------------------------------------------------ + /// Call this to set the lldb in the mode where it breaks on new thread + /// creations, and then auto-restarts. This is useful when you are trying + /// to run only one thread, but either that thread or the kernel is creating + /// new threads in the process. If you stop when the thread is created, you + /// can immediately suspend it, and keep executing only the one thread you intend. + /// + /// @return + /// Returns \b true if we were able to start up the notification + /// \b false otherwise. + //------------------------------------------------------------------ + virtual bool + StartNoticingNewThreads() + { + return true; + } + + //------------------------------------------------------------------ + /// Call this to turn off the stop & notice new threads mode. + /// + /// @return + /// Returns \b true if we were able to start up the notification + /// \b false otherwise. + //------------------------------------------------------------------ + virtual bool + StopNoticingNewThreads() + { + return true; + } + + void + SetRunningUserExpression (bool on); + + //------------------------------------------------------------------ + // lldb::ExecutionContextScope pure virtual functions + //------------------------------------------------------------------ + virtual lldb::TargetSP + CalculateTarget (); + + virtual lldb::ProcessSP + CalculateProcess () + { + return shared_from_this(); + } + + virtual lldb::ThreadSP + CalculateThread () + { + return lldb::ThreadSP(); + } + + virtual lldb::StackFrameSP + CalculateStackFrame () + { + return lldb::StackFrameSP(); + } + + virtual void + CalculateExecutionContext (ExecutionContext &exe_ctx); + + void + SetSTDIOFileDescriptor (int file_descriptor); + + //------------------------------------------------------------------ + // Add a permanent region of memory that should never be read or + // written to. This can be used to ensure that memory reads or writes + // to certain areas of memory never end up being sent to the + // DoReadMemory or DoWriteMemory functions which can improve + // performance. + //------------------------------------------------------------------ + void + AddInvalidMemoryRegion (const LoadRange ®ion); + + //------------------------------------------------------------------ + // Remove a permanent region of memory that should never be read or + // written to that was previously added with AddInvalidMemoryRegion. + //------------------------------------------------------------------ + bool + RemoveInvalidMemoryRange (const LoadRange ®ion); + + //------------------------------------------------------------------ + // If the setup code of a thread plan needs to do work that might involve + // calling a function in the target, it should not do that work directly + // in one of the thread plan functions (DidPush/WillResume) because + // such work needs to be handled carefully. Instead, put that work in + // a PreResumeAction callback, and register it with the process. It will + // get done before the actual "DoResume" gets called. + //------------------------------------------------------------------ + + typedef bool (PreResumeActionCallback)(void *); + + void + AddPreResumeAction (PreResumeActionCallback callback, void *baton); + + bool + RunPreResumeActions (); + + void + ClearPreResumeActions (); + + ProcessRunLock & + GetRunLock () + { + if (Host::GetCurrentThread() == m_private_state_thread) + return m_private_run_lock; + else + return m_public_run_lock; + } + +protected: + //------------------------------------------------------------------ + // NextEventAction provides a way to register an action on the next + // event that is delivered to this process. There is currently only + // one next event action allowed in the process at one time. If a + // new "NextEventAction" is added while one is already present, the + // old action will be discarded (with HandleBeingUnshipped called + // after it is discarded.) + // + // If you want to resume the process as a result of a resume action, + // call RequestResume, don't call Resume directly. + //------------------------------------------------------------------ + class NextEventAction + { + public: + typedef enum EventActionResult + { + eEventActionSuccess, + eEventActionRetry, + eEventActionExit + } EventActionResult; + + NextEventAction (Process *process) : + m_process(process) + { + } + + virtual + ~NextEventAction() + { + } + + virtual EventActionResult PerformAction (lldb::EventSP &event_sp) = 0; + virtual void HandleBeingUnshipped () {} + virtual EventActionResult HandleBeingInterrupted () = 0; + virtual const char *GetExitString() = 0; + void RequestResume() + { + m_process->m_resume_requested = true; + } + protected: + Process *m_process; + }; + + void SetNextEventAction (Process::NextEventAction *next_event_action) + { + if (m_next_event_action_ap.get()) + m_next_event_action_ap->HandleBeingUnshipped(); + + m_next_event_action_ap.reset(next_event_action); + } + + // This is the completer for Attaching: + class AttachCompletionHandler : public NextEventAction + { + public: + AttachCompletionHandler (Process *process, uint32_t exec_count) : + NextEventAction (process), + m_exec_count (exec_count) + { + } + + virtual + ~AttachCompletionHandler() + { + } + + virtual EventActionResult PerformAction (lldb::EventSP &event_sp); + virtual EventActionResult HandleBeingInterrupted (); + virtual const char *GetExitString(); + private: + uint32_t m_exec_count; + std::string m_exit_string; + }; + + bool + HijackPrivateProcessEvents (Listener *listener); + + void + RestorePrivateProcessEvents (); + + bool + PrivateStateThreadIsValid () const + { + return IS_VALID_LLDB_HOST_THREAD(m_private_state_thread); + } + + //------------------------------------------------------------------ + // Type definitions + //------------------------------------------------------------------ + typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection; + + struct PreResumeCallbackAndBaton + { + bool (*callback) (void *); + void *baton; + PreResumeCallbackAndBaton (PreResumeActionCallback in_callback, void *in_baton) : + callback (in_callback), + baton (in_baton) + { + } + }; + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + Target & m_target; ///< The target that owns this process. + ThreadSafeValue<lldb::StateType> m_public_state; + ThreadSafeValue<lldb::StateType> m_private_state; // The actual state of our process + Broadcaster m_private_state_broadcaster; // This broadcaster feeds state changed events into the private state thread's listener. + Broadcaster m_private_state_control_broadcaster; // This is the control broadcaster, used to pause, resume & stop the private state thread. + Listener m_private_state_listener; // This is the listener for the private state thread. + Predicate<bool> m_private_state_control_wait; /// This Predicate is used to signal that a control operation is complete. + lldb::thread_t m_private_state_thread; // Thread ID for the thread that watches interal state events + ProcessModID m_mod_id; ///< Tracks the state of the process over stops and other alterations. + uint32_t m_process_unique_id; ///< Each lldb_private::Process class that is created gets a unique integer ID that increments with each new instance + uint32_t m_thread_index_id; ///< Each thread is created with a 1 based index that won't get re-used. + std::map<uint64_t, uint32_t> m_thread_id_to_index_id_map; + int m_exit_status; ///< The exit status of the process, or -1 if not set. + std::string m_exit_string; ///< A textual description of why a process exited. + Mutex m_thread_mutex; + ThreadList m_thread_list_real; ///< The threads for this process as are known to the protocol we are debugging with + ThreadList m_thread_list; ///< The threads for this process as the user will see them. This is usually the same as + ///< m_thread_list_real, but might be different if there is an OS plug-in creating memory threads + std::vector<Notifications> m_notifications; ///< The list of notifications that this process can deliver. + std::vector<lldb::addr_t> m_image_tokens; + Listener &m_listener; + BreakpointSiteList m_breakpoint_site_list; ///< This is the list of breakpoint locations we intend to insert in the target. + std::unique_ptr<DynamicLoader> m_dyld_ap; + std::unique_ptr<DynamicCheckerFunctions> m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use. + std::unique_ptr<OperatingSystem> m_os_ap; + UnixSignals m_unix_signals; /// This is the current signal set for this process. + lldb::ABISP m_abi_sp; + lldb::InputReaderSP m_process_input_reader; + Communication m_stdio_communication; + Mutex m_stdio_communication_mutex; + std::string m_stdout_data; + std::string m_stderr_data; + Mutex m_profile_data_comm_mutex; + std::vector<std::string> m_profile_data; + MemoryCache m_memory_cache; + AllocatedMemoryCache m_allocated_memory_cache; + bool m_should_detach; /// Should we detach if the process object goes away with an explicit call to Kill or Detach? + LanguageRuntimeCollection m_language_runtimes; + std::unique_ptr<NextEventAction> m_next_event_action_ap; + std::vector<PreResumeCallbackAndBaton> m_pre_resume_actions; + ProcessRunLock m_public_run_lock; + ProcessRunLock m_private_run_lock; + Predicate<bool> m_currently_handling_event; // This predicate is set in HandlePrivateEvent while all its business is being done. + bool m_currently_handling_do_on_removals; + bool m_resume_requested; // If m_currently_handling_event or m_currently_handling_do_on_removals are true, Resume will only request a resume, using this flag to check. + bool m_finalize_called; + bool m_clear_thread_plans_on_stop; + lldb::StateType m_last_broadcast_state; /// This helps with the Public event coalescing in ShouldBroadcastEvent. + bool m_destroy_in_process; + + enum { + eCanJITDontKnow= 0, + eCanJITYes, + eCanJITNo + } m_can_jit; + + size_t + RemoveBreakpointOpcodesFromBuffer (lldb::addr_t addr, size_t size, uint8_t *buf) const; + + void + SynchronouslyNotifyStateChanged (lldb::StateType state); + + void + SetPublicState (lldb::StateType new_state, bool restarted); + + void + SetPrivateState (lldb::StateType state); + + bool + StartPrivateStateThread (bool force = false); + + void + StopPrivateStateThread (); + + void + PausePrivateStateThread (); + + void + ResumePrivateStateThread (); + + static void * + PrivateStateThread (void *arg); + + void * + RunPrivateStateThread (); + + void + HandlePrivateEvent (lldb::EventSP &event_sp); + + lldb::StateType + WaitForProcessStopPrivate (const TimeValue *timeout, lldb::EventSP &event_sp); + + // This waits for both the state change broadcaster, and the control broadcaster. + // If control_only, it only waits for the control broadcaster. + + bool + WaitForEventsPrivate (const TimeValue *timeout, lldb::EventSP &event_sp, bool control_only); + + lldb::StateType + WaitForStateChangedEventsPrivate (const TimeValue *timeout, lldb::EventSP &event_sp); + + lldb::StateType + WaitForState (const TimeValue *timeout, + const lldb::StateType *match_states, + const uint32_t num_match_states); + + size_t + WriteMemoryPrivate (lldb::addr_t addr, const void *buf, size_t size, Error &error); + + void + AppendSTDOUT (const char *s, size_t len); + + void + AppendSTDERR (const char *s, size_t len); + + void + BroadcastAsyncProfileData(const std::string &one_profile_data); + + static void + STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len); + + void + PushProcessInputReader (); + + void + PopProcessInputReader (); + + void + ResetProcessInputReader (); + + static size_t + ProcessInputReaderCallback (void *baton, + InputReader &reader, + lldb::InputReaderAction notification, + const char *bytes, + size_t bytes_len); + + Error + HaltForDestroyOrDetach(lldb::EventSP &exit_event_sp); + +private: + //------------------------------------------------------------------ + // For Process only + //------------------------------------------------------------------ + void ControlPrivateStateThread (uint32_t signal); + + DISALLOW_COPY_AND_ASSIGN (Process); + +}; + +} // namespace lldb_private + +#endif // liblldb_Process_h_ diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h new file mode 100644 index 0000000..dd0e73f --- /dev/null +++ b/include/lldb/Target/RegisterContext.h @@ -0,0 +1,213 @@ +//===-- RegisterContext.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_RegisterContext_h_ +#define liblldb_RegisterContext_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/ExecutionContextScope.h" + +namespace lldb_private { + +class RegisterContext : + public std::enable_shared_from_this<RegisterContext>, + public ExecutionContextScope +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + RegisterContext (Thread &thread, uint32_t concrete_frame_idx); + + virtual + ~RegisterContext (); + + void + InvalidateIfNeeded (bool force); + + //------------------------------------------------------------------ + // Subclasses must override these functions + //------------------------------------------------------------------ + virtual void + InvalidateAllRegisters () = 0; + + virtual size_t + GetRegisterCount () = 0; + + virtual const RegisterInfo * + GetRegisterInfoAtIndex (size_t reg) = 0; + + virtual size_t + GetRegisterSetCount () = 0; + + virtual const RegisterSet * + GetRegisterSet (size_t reg_set) = 0; + + virtual bool + ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) = 0; + + virtual bool + WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) = 0; + + // These two functions are used to implement "push" and "pop" of register states. They are used primarily + // for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then + // restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues. + // ReadAllRegisters will do what is necessary to return a coherent set of register values for this thread, which + // may mean e.g. interrupting a thread that is sitting in a kernel trap. That is a somewhat disruptive operation, + // so these API's should only be used when this behavior is needed. + + virtual bool + ReadAllRegisterValues (lldb::DataBufferSP &data_sp) = 0; + + virtual bool + WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0; + + bool + CopyFromRegisterContext (lldb::RegisterContextSP context); + + virtual uint32_t + ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) = 0; + + //------------------------------------------------------------------ + // Subclasses can override these functions if desired + //------------------------------------------------------------------ + virtual uint32_t + NumSupportedHardwareBreakpoints (); + + virtual uint32_t + SetHardwareBreakpoint (lldb::addr_t addr, size_t size); + + virtual bool + ClearHardwareBreakpoint (uint32_t hw_idx); + + virtual uint32_t + NumSupportedHardwareWatchpoints (); + + virtual uint32_t + SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write); + + virtual bool + ClearHardwareWatchpoint (uint32_t hw_index); + + virtual bool + HardwareSingleStep (bool enable); + + virtual Error + ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue ®_value); + + virtual Error + WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue ®_value); + + //------------------------------------------------------------------ + // Subclasses should not override these + //------------------------------------------------------------------ + virtual lldb::tid_t + GetThreadID() const; + + virtual Thread & + GetThread () + { + return m_thread; + } + + const RegisterInfo * + GetRegisterInfoByName (const char *reg_name, uint32_t start_idx = 0); + + uint64_t + GetPC (uint64_t fail_value = LLDB_INVALID_ADDRESS); + + bool + SetPC (uint64_t pc); + + uint64_t + GetSP (uint64_t fail_value = LLDB_INVALID_ADDRESS); + + bool + SetSP (uint64_t sp); + + uint64_t + GetFP (uint64_t fail_value = LLDB_INVALID_ADDRESS); + + bool + SetFP (uint64_t fp); + + const char * + GetRegisterName (uint32_t reg); + + uint64_t + GetReturnAddress (uint64_t fail_value = LLDB_INVALID_ADDRESS); + + uint64_t + GetFlags (uint64_t fail_value = 0); + + uint64_t + ReadRegisterAsUnsigned (uint32_t reg, uint64_t fail_value); + + uint64_t + ReadRegisterAsUnsigned (const RegisterInfo *reg_info, uint64_t fail_value); + + bool + WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval); + + bool + WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval); + bool + ConvertBetweenRegisterKinds (int source_rk, uint32_t source_regnum, int target_rk, uint32_t& target_regnum); + + //------------------------------------------------------------------ + // lldb::ExecutionContextScope pure virtual functions + //------------------------------------------------------------------ + virtual lldb::TargetSP + CalculateTarget (); + + virtual lldb::ProcessSP + CalculateProcess (); + + virtual lldb::ThreadSP + CalculateThread (); + + virtual lldb::StackFrameSP + CalculateStackFrame (); + + virtual void + CalculateExecutionContext (ExecutionContext &exe_ctx); + + uint32_t + GetStopID () const + { + return m_stop_id; + } + + void + SetStopID (uint32_t stop_id) + { + m_stop_id = stop_id; + } + +protected: + //------------------------------------------------------------------ + // Classes that inherit from RegisterContext can see and modify these + //------------------------------------------------------------------ + Thread &m_thread; // The thread that this register context belongs to. + uint32_t m_concrete_frame_idx; // The concrete frame index for this register context + uint32_t m_stop_id; // The stop ID that any data in this context is valid for +private: + //------------------------------------------------------------------ + // For RegisterContext only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (RegisterContext); +}; + +} // namespace lldb_private + +#endif // liblldb_RegisterContext_h_ diff --git a/include/lldb/Target/SectionLoadList.h b/include/lldb/Target/SectionLoadList.h new file mode 100644 index 0000000..ac05bf7 --- /dev/null +++ b/include/lldb/Target/SectionLoadList.h @@ -0,0 +1,89 @@ +//===-- SectionLoadList.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_SectionLoadList_h_ +#define liblldb_SectionLoadList_h_ + +// C Includes +// C++ Includes +#include <map> + +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class SectionLoadList +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SectionLoadList () : + m_addr_to_sect (), + m_sect_to_addr (), + m_mutex (Mutex::eMutexTypeRecursive) + + { + } + + ~SectionLoadList() + { + // Call clear since this takes a lock and clears the section load list + // in case another thread is currently using this section load list + Clear(); + } + + bool + IsEmpty() const; + + void + Clear (); + + lldb::addr_t + GetSectionLoadAddress (const lldb::SectionSP §ion_sp) const; + + bool + ResolveLoadAddress (lldb::addr_t load_addr, Address &so_addr) const; + + bool + SetSectionLoadAddress (const lldb::SectionSP §ion_sp, lldb::addr_t load_addr, bool warn_multiple = false); + + // The old load address should be specified when unloading to ensure we get + // the correct instance of the section as a shared library could be loaded + // at more than one location. + bool + SetSectionUnloaded (const lldb::SectionSP §ion_sp, lldb::addr_t load_addr); + + // Unload all instances of a section. This function can be used on systems + // that don't support multiple copies of the same shared library to be + // loaded at the same time. + size_t + SetSectionUnloaded (const lldb::SectionSP §ion_sp); + + void + Dump (Stream &s, Target *target); + +protected: + typedef std::map<lldb::addr_t, lldb::SectionSP> addr_to_sect_collection; + typedef llvm::DenseMap<const Section *, lldb::addr_t> sect_to_addr_collection; + addr_to_sect_collection m_addr_to_sect; + sect_to_addr_collection m_sect_to_addr; + mutable Mutex m_mutex; + +private: + DISALLOW_COPY_AND_ASSIGN (SectionLoadList); +}; + +} // namespace lldb_private + +#endif // liblldb_SectionLoadList_h_ diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h new file mode 100644 index 0000000..877bd8c --- /dev/null +++ b/include/lldb/Target/StackFrame.h @@ -0,0 +1,207 @@ +//===-- StackFrame.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_StackFrame_h_ +#define liblldb_StackFrame_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Error.h" +#include "lldb/Core/Flags.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/UserID.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/StackID.h" + +namespace lldb_private { + +class StackFrame : + public std::enable_shared_from_this<StackFrame>, + public ExecutionContextScope +{ +public: + enum ExpressionPathOption + { + eExpressionPathOptionCheckPtrVsMember = (1u << 0), + eExpressionPathOptionsNoFragileObjcIvar = (1u << 1), + eExpressionPathOptionsNoSyntheticChildren = (1u << 2), + eExpressionPathOptionsNoSyntheticArrayRange = (1u << 3), + eExpressionPathOptionsAllowDirectIVarAccess = (1u << 4) + }; + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StackFrame (const lldb::ThreadSP &thread_sp, + lldb::user_id_t frame_idx, + lldb::user_id_t concrete_frame_idx, + lldb::addr_t cfa, + lldb::addr_t pc, + const SymbolContext *sc_ptr); + + StackFrame (const lldb::ThreadSP &thread_sp, + lldb::user_id_t frame_idx, + lldb::user_id_t concrete_frame_idx, + const lldb::RegisterContextSP ®_context_sp, + lldb::addr_t cfa, + lldb::addr_t pc, + const SymbolContext *sc_ptr); + + StackFrame (const lldb::ThreadSP &thread_sp, + lldb::user_id_t frame_idx, + lldb::user_id_t concrete_frame_idx, + const lldb::RegisterContextSP ®_context_sp, + lldb::addr_t cfa, + const Address& pc, + const SymbolContext *sc_ptr); + + virtual ~StackFrame (); + + lldb::ThreadSP + GetThread () const + { + return m_thread_wp.lock(); + } + + StackID& + GetStackID(); + + const Address& + GetFrameCodeAddress(); + + void + ChangePC (lldb::addr_t pc); + + const SymbolContext& + GetSymbolContext (uint32_t resolve_scope); + + bool + GetFrameBaseValue(Scalar &value, Error *error_ptr); + + Block * + GetFrameBlock (); + + lldb::RegisterContextSP + GetRegisterContext (); + + const lldb::RegisterContextSP & + GetRegisterContextSP () const + { + return m_reg_context_sp; + } + + VariableList * + GetVariableList (bool get_file_globals); + + lldb::VariableListSP + GetInScopeVariableList (bool get_file_globals); + + // See ExpressionPathOption enumeration for "options" values + lldb::ValueObjectSP + GetValueForVariableExpressionPath (const char *var_expr, + lldb::DynamicValueType use_dynamic, + uint32_t options, + lldb::VariableSP &var_sp, + Error &error); + + bool + HasDebugInformation (); + + const char * + Disassemble (); + + void + DumpUsingSettingsFormat (Stream *strm); + + void + Dump (Stream *strm, bool show_frame_index, bool show_fullpaths); + + bool + IsInlined (); + + uint32_t + GetFrameIndex () const; + + uint32_t + GetConcreteFrameIndex () const + { + return m_concrete_frame_index; + } + + lldb::ValueObjectSP + GetValueObjectForFrameVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic); + + lldb::ValueObjectSP + TrackGlobalVariable (const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic); + + //------------------------------------------------------------------ + // lldb::ExecutionContextScope pure virtual functions + //------------------------------------------------------------------ + virtual lldb::TargetSP + CalculateTarget (); + + virtual lldb::ProcessSP + CalculateProcess (); + + virtual lldb::ThreadSP + CalculateThread (); + + virtual lldb::StackFrameSP + CalculateStackFrame (); + + virtual void + CalculateExecutionContext (ExecutionContext &exe_ctx); + + bool + GetStatus (Stream &strm, + bool show_frame_info, + bool show_source); + +protected: + friend class StackFrameList; + + void + SetSymbolContextScope (SymbolContextScope *symbol_scope); + + void + UpdateCurrentFrameFromPreviousFrame (StackFrame &prev_frame); + + void + UpdatePreviousFrameFromCurrentFrame (StackFrame &curr_frame); + + bool + HasCachedData () const; + +private: + //------------------------------------------------------------------ + // For StackFrame only + //------------------------------------------------------------------ + lldb::ThreadWP m_thread_wp; + uint32_t m_frame_index; + uint32_t m_concrete_frame_index; + lldb::RegisterContextSP m_reg_context_sp; + StackID m_id; + Address m_frame_code_addr; // The frame code address (might not be the same as the actual PC for inlined frames) as a section/offset address + SymbolContext m_sc; + Flags m_flags; + Scalar m_frame_base; + Error m_frame_base_error; + lldb::VariableListSP m_variable_list_sp; + ValueObjectList m_variable_list_value_objects; // Value objects for each variable in m_variable_list_sp + StreamString m_disassembly; + DISALLOW_COPY_AND_ASSIGN (StackFrame); +}; + +} // namespace lldb_private + +#endif // liblldb_StackFrame_h_ diff --git a/include/lldb/Target/StackFrameList.h b/include/lldb/Target/StackFrameList.h new file mode 100644 index 0000000..b2689d0 --- /dev/null +++ b/include/lldb/Target/StackFrameList.h @@ -0,0 +1,157 @@ +//===-- StackFrameList.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_StackFrameList_h_ +#define liblldb_StackFrameList_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/Host/Mutex.h" +#include "lldb/Target/StackFrame.h" + +namespace lldb_private { + +class StackFrameList +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StackFrameList (Thread &thread, + const lldb::StackFrameListSP &prev_frames_sp, + bool show_inline_frames); + + ~StackFrameList(); + + uint32_t + GetNumFrames (bool can_create = true); + + lldb::StackFrameSP + GetFrameAtIndex (uint32_t idx); + + lldb::StackFrameSP + GetFrameWithConcreteFrameIndex (uint32_t unwind_idx); + + lldb::StackFrameSP + GetFrameWithStackID (const StackID &stack_id); + + // Mark a stack frame as the current frame + uint32_t + SetSelectedFrame (lldb_private::StackFrame *frame); + + uint32_t + GetSelectedFrameIndex () const; + + // Mark a stack frame as the current frame using the frame index + bool + SetSelectedFrameByIndex (uint32_t idx); + + uint32_t + GetVisibleStackFrameIndex(uint32_t idx) + { + if (m_current_inlined_depth < UINT32_MAX) + return idx - m_current_inlined_depth; + else + return idx; + } + + void + CalculateCurrentInlinedDepth (); + + void + SetDefaultFileAndLineToSelectedFrame(); + + void + Clear (); + + void + InvalidateFrames (uint32_t start_idx); + + void + Dump (Stream *s); + + lldb::StackFrameSP + GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr); + + size_t + GetStatus (Stream &strm, + uint32_t first_frame, + uint32_t num_frames, + bool show_frame_info, + uint32_t num_frames_with_source); + +protected: + + friend class Thread; + + bool + SetFrameAtIndex (uint32_t idx, lldb::StackFrameSP &frame_sp); + + static void + Merge (std::unique_ptr<StackFrameList>& curr_ap, + lldb::StackFrameListSP& prev_sp); + + void + GetFramesUpTo (uint32_t end_idx); + + bool + GetAllFramesFetched() + { + return m_concrete_frames_fetched == UINT32_MAX; + } + + void + SetAllFramesFetched () + { + m_concrete_frames_fetched = UINT32_MAX; + } + + bool + DecrementCurrentInlinedDepth (); + + void + ResetCurrentInlinedDepth(); + + uint32_t + GetCurrentInlinedDepth (); + + void + SetCurrentInlinedDepth (uint32_t new_depth); + + //------------------------------------------------------------------ + // Classes that inherit from StackFrameList can see and modify these + //------------------------------------------------------------------ + typedef std::vector<lldb::StackFrameSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + Thread &m_thread; + lldb::StackFrameListSP m_prev_frames_sp; + mutable Mutex m_mutex; + collection m_frames; + uint32_t m_selected_frame_idx; + uint32_t m_concrete_frames_fetched; + uint32_t m_current_inlined_depth; + lldb::addr_t m_current_inlined_pc; + bool m_show_inlined_frames; + +private: + //------------------------------------------------------------------ + // For StackFrameList only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (StackFrameList); +}; + +} // namespace lldb_private + +#endif // liblldb_StackFrameList_h_ diff --git a/include/lldb/Target/StackID.h b/include/lldb/Target/StackID.h new file mode 100644 index 0000000..7e713c7 --- /dev/null +++ b/include/lldb/Target/StackID.h @@ -0,0 +1,149 @@ +//===-- StackID.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_StackID_h_ +#define liblldb_StackID_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" + +namespace lldb_private { + +class StackID +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StackID () : + m_pc (LLDB_INVALID_ADDRESS), + m_cfa (LLDB_INVALID_ADDRESS), + m_symbol_scope (NULL) + { + } + + explicit + StackID (lldb::addr_t pc, lldb::addr_t cfa, SymbolContextScope *symbol_scope) : + m_pc (pc), + m_cfa (cfa), + m_symbol_scope (symbol_scope) + { + } + + StackID (const StackID& rhs) : + m_pc (rhs.m_pc), + m_cfa (rhs.m_cfa), + m_symbol_scope (rhs.m_symbol_scope) + { + } + + ~StackID() + { + } + + lldb::addr_t + GetPC() const + { + return m_pc; + } + + lldb::addr_t + GetCallFrameAddress() const + { + return m_cfa; + } + + SymbolContextScope * + GetSymbolContextScope () const + { + return m_symbol_scope; + } + + void + SetSymbolContextScope (SymbolContextScope *symbol_scope) + { + m_symbol_scope = symbol_scope; + } + + void + Clear () + { + m_pc = LLDB_INVALID_ADDRESS; + m_cfa = LLDB_INVALID_ADDRESS; + m_symbol_scope = NULL; + } + + bool + IsValid () const + { + return m_pc != LLDB_INVALID_ADDRESS || m_cfa != LLDB_INVALID_ADDRESS; + } + + void + Dump (Stream *s); + + //------------------------------------------------------------------ + // Operators + //------------------------------------------------------------------ + const StackID& + operator=(const StackID& rhs) + { + if (this != &rhs) + { + m_pc = rhs.m_pc; + m_cfa = rhs.m_cfa; + m_symbol_scope = rhs.m_symbol_scope; + } + return *this; + } + +protected: + + friend class StackFrame; + + void + SetPC (lldb::addr_t pc) + { + m_pc = pc; + } + + + //------------------------------------------------------------------ + // Classes that inherit from StackID can see and modify these + //------------------------------------------------------------------ + lldb::addr_t m_pc; // The pc value for the function/symbol for this frame. This will + // only get used if the symbol scope is NULL (the code where we are + // stopped is not represented by any function or symbol in any + // shared library). + lldb::addr_t m_cfa; // The call frame address (stack pointer) value + // at the beginning of the function that uniquely + // identifies this frame (along with m_symbol_scope below) + SymbolContextScope *m_symbol_scope; // If NULL, there is no block or symbol for this frame. + // If not NULL, this will either be the scope for the + // lexical block for the frame, or the scope + // for the symbol. Symbol context scopes are + // always be unique pointers since the are part + // of the Block and Symbol objects and can easily + // be used to tell if a stack ID is the same as + // another. +}; + +bool operator== (const StackID& lhs, const StackID& rhs); +bool operator!= (const StackID& lhs, const StackID& rhs); + +// frame_id_1 < frame_id_2 means "frame_id_1 is YOUNGER than frame_id_2" +bool operator< (const StackID& lhs, const StackID& rhs); + +} // namespace lldb_private + +#endif // liblldb_StackID_h_ diff --git a/include/lldb/Target/StopInfo.h b/include/lldb/Target/StopInfo.h new file mode 100644 index 0000000..3435d39 --- /dev/null +++ b/include/lldb/Target/StopInfo.h @@ -0,0 +1,227 @@ +//===-- StopInfo.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_StopInfo_h_ +#define liblldb_StopInfo_h_ + +// C Includes +// C++ Includes +#include <string> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Target/Process.h" + +namespace lldb_private { + +class StopInfo +{ + friend class Process::ProcessEventData; + friend class ThreadPlanBase; + +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + StopInfo (Thread &thread, uint64_t value); + + virtual ~StopInfo() + { + } + + + bool + IsValid () const; + + void + SetThread (const lldb::ThreadSP &thread_sp) + { + m_thread_wp = thread_sp; + } + + lldb::ThreadSP + GetThread() const + { + return m_thread_wp.lock(); + } + + // The value of the StopInfo depends on the StopReason. + // StopReason Meaning + // ---------------------------------------------- + // eStopReasonBreakpoint BreakpointSiteID + // eStopReasonSignal Signal number + // eStopReasonWatchpoint WatchpointLocationID + // eStopReasonPlanComplete No significance + + uint64_t + GetValue() const + { + return m_value; + } + + virtual lldb::StopReason + GetStopReason () const = 0; + + // ShouldStopSynchronous will get called before any thread plans are consulted, and if it says we should + // resume the target, then we will just immediately resume. This should not run any code in or resume the + // target. + + virtual bool + ShouldStopSynchronous (Event *event_ptr) + { + return true; + } + + void + OverrideShouldNotify (bool override_value) + { + m_override_should_notify = override_value ? eLazyBoolYes : eLazyBoolNo; + } + + // If should stop returns false, check if we should notify of this event + virtual bool + ShouldNotify (Event *event_ptr) + { + if (m_override_should_notify == eLazyBoolCalculate) + return DoShouldNotify (event_ptr); + else + return m_override_should_notify == eLazyBoolYes; + } + + virtual void + WillResume (lldb::StateType resume_state) + { + // By default, don't do anything + } + + virtual const char * + GetDescription () + { + return m_description.c_str(); + } + + virtual void + SetDescription (const char *desc_cstr) + { + if (desc_cstr && desc_cstr[0]) + m_description.assign (desc_cstr); + else + m_description.clear(); + } + + // Sometimes the thread plan logic will know that it wants a given stop to stop or not, + // regardless of what the ordinary logic for that StopInfo would dictate. The main example + // of this is the ThreadPlanCallFunction, which for instance knows - based on how that particular + // expression was executed - whether it wants all breakpoints to auto-continue or not. + // Use OverrideShouldStop on the StopInfo to implement this. + + void + OverrideShouldStop (bool override_value) + { + m_override_should_stop = override_value ? eLazyBoolYes : eLazyBoolNo; + } + + bool + GetOverrideShouldStop() + { + return m_override_should_stop != eLazyBoolCalculate; + } + + bool + GetOverriddenShouldStopValue () + { + return m_override_should_stop == eLazyBoolYes; + } + + static lldb::StopInfoSP + CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id); + + // This creates a StopInfo for the thread where the should_stop is already set, and won't be recalculated. + static lldb::StopInfoSP + CreateStopReasonWithBreakpointSiteID (Thread &thread, lldb::break_id_t break_id, bool should_stop); + + static lldb::StopInfoSP + CreateStopReasonWithWatchpointID (Thread &thread, lldb::break_id_t watch_id); + + static lldb::StopInfoSP + CreateStopReasonWithSignal (Thread &thread, int signo); + + static lldb::StopInfoSP + CreateStopReasonToTrace (Thread &thread); + + static lldb::StopInfoSP + CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan, lldb::ValueObjectSP return_valobj_sp); + + static lldb::StopInfoSP + CreateStopReasonWithException (Thread &thread, const char *description); + + static lldb::StopInfoSP + CreateStopReasonWithExec (Thread &thread); + + static lldb::ValueObjectSP + GetReturnValueObject (lldb::StopInfoSP &stop_info_sp); + +protected: + // Perform any action that is associated with this stop. This is done as the + // Event is removed from the event queue. ProcessEventData::DoOnRemoval does the job. + + virtual void + PerformAction (Event *event_ptr) + { + } + + virtual bool + DoShouldNotify (Event *event_ptr) + { + return false; + } + + // Stop the thread by default. Subclasses can override this to allow + // the thread to continue if desired. The ShouldStop method should not do anything + // that might run code. If you need to run code when deciding whether to stop + // at this StopInfo, that must be done in the PerformAction. + // The PerformAction will always get called before the ShouldStop. This is done by the + // ProcessEventData::DoOnRemoval, though the ThreadPlanBase needs to consult this later on. + virtual bool + ShouldStop (Event *event_ptr) + { + return true; + } + + //------------------------------------------------------------------ + // Classes that inherit from StackID can see and modify these + //------------------------------------------------------------------ + lldb::ThreadWP m_thread_wp; // The thread corresponding to the stop reason. + uint32_t m_stop_id; // The process stop ID for which this stop info is valid + uint32_t m_resume_id; // This is the resume ID when we made this stop ID. + uint64_t m_value; // A generic value that can be used for things pertaining to this stop info + std::string m_description; // A textual description describing this stop. + LazyBool m_override_should_notify; + LazyBool m_override_should_stop; + + // This determines whether the target has run since this stop info. + // N.B. running to evaluate a user expression does not count. + bool HasTargetRunSinceMe (); + + // MakeStopInfoValid is necessary to allow saved stop infos to resurrect themselves as valid. + // It should only be used by Thread::RestoreThreadStateFromCheckpoint and to make sure the one-step + // needed for before-the-fact watchpoints does not prevent us from stopping + void + MakeStopInfoValid (); + +private: + friend class Thread; + + DISALLOW_COPY_AND_ASSIGN (StopInfo); +}; + +} // namespace lldb_private + +#endif // liblldb_StopInfo_h_ diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h new file mode 100644 index 0000000..87fa57b --- /dev/null +++ b/include/lldb/Target/Target.h @@ -0,0 +1,1223 @@ +//===-- Target.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_Target_h_ +#define liblldb_Target_h_ + +// C Includes +// C++ Includes +#include <list> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Breakpoint/BreakpointList.h" +#include "lldb/Breakpoint/BreakpointLocationCollection.h" +#include "lldb/Breakpoint/WatchpointList.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Disassembler.h" +#include "lldb/Core/Event.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/UserSettingsController.h" +#include "lldb/Expression/ClangPersistentVariables.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Interpreter/OptionValueBoolean.h" +#include "lldb/Interpreter/OptionValueEnumeration.h" +#include "lldb/Interpreter/OptionValueFileSpec.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/PathMappingList.h" +#include "lldb/Target/SectionLoadList.h" + +namespace lldb_private { + +extern OptionEnumValueElement g_dynamic_value_types[]; + +typedef enum InlineStrategy +{ + eInlineBreakpointsNever = 0, + eInlineBreakpointsHeaders, + eInlineBreakpointsAlways +} InlineStrategy; + +typedef enum LoadScriptFromSymFile +{ + eLoadScriptFromSymFileTrue, + eLoadScriptFromSymFileFalse, + eLoadScriptFromSymFileWarn +} LoadScriptFromSymFile; + +//---------------------------------------------------------------------- +// TargetProperties +//---------------------------------------------------------------------- +class TargetProperties : public Properties +{ +public: + TargetProperties(Target *target); + + virtual + ~TargetProperties(); + + ArchSpec + GetDefaultArchitecture () const; + + void + SetDefaultArchitecture (const ArchSpec& arch); + + lldb::DynamicValueType + GetPreferDynamicValue() const; + + bool + GetDisableASLR () const; + + void + SetDisableASLR (bool b); + + bool + GetDisableSTDIO () const; + + void + SetDisableSTDIO (bool b); + + const char * + GetDisassemblyFlavor() const; + +// void +// SetDisassemblyFlavor(const char *flavor); + + InlineStrategy + GetInlineStrategy () const; + + const char * + GetArg0 () const; + + void + SetArg0 (const char *arg); + + bool + GetRunArguments (Args &args) const; + + void + SetRunArguments (const Args &args); + + size_t + GetEnvironmentAsArgs (Args &env) const; + + bool + GetSkipPrologue() const; + + PathMappingList & + GetSourcePathMap () const; + + FileSpecList & + GetExecutableSearchPaths (); + + FileSpecList & + GetDebugFileSearchPaths (); + + bool + GetEnableSyntheticValue () const; + + uint32_t + GetMaximumNumberOfChildrenToDisplay() const; + + uint32_t + GetMaximumSizeOfStringSummary() const; + + uint32_t + GetMaximumMemReadSize () const; + + FileSpec + GetStandardInputPath () const; + + void + SetStandardInputPath (const char *path); + + FileSpec + GetStandardOutputPath () const; + + void + SetStandardOutputPath (const char *path); + + FileSpec + GetStandardErrorPath () const; + + void + SetStandardErrorPath (const char *path); + + bool + GetBreakpointsConsultPlatformAvoidList (); + + const char * + GetExpressionPrefixContentsAsCString (); + + bool + GetUseHexImmediates() const; + + bool + GetUseFastStepping() const; + + LoadScriptFromSymFile + GetLoadScriptFromSymbolFile() const; + + Disassembler::HexImmediateStyle + GetHexImmediateStyle() const; + + MemoryModuleLoadLevel + GetMemoryModuleLoadLevel() const; + +}; + +typedef std::shared_ptr<TargetProperties> TargetPropertiesSP; + +class EvaluateExpressionOptions +{ +public: + static const uint32_t default_timeout = 500000; + EvaluateExpressionOptions() : + m_execution_policy(eExecutionPolicyOnlyWhenNeeded), + m_coerce_to_id(false), + m_unwind_on_error(true), + m_ignore_breakpoints (false), + m_keep_in_memory(false), + m_run_others(true), + m_use_dynamic(lldb::eNoDynamicValues), + m_timeout_usec(default_timeout) + {} + + ExecutionPolicy + GetExecutionPolicy () const + { + return m_execution_policy; + } + + EvaluateExpressionOptions& + SetExecutionPolicy (ExecutionPolicy policy = eExecutionPolicyAlways) + { + m_execution_policy = policy; + return *this; + } + + bool + DoesCoerceToId () const + { + return m_coerce_to_id; + } + + EvaluateExpressionOptions& + SetCoerceToId (bool coerce = true) + { + m_coerce_to_id = coerce; + return *this; + } + + bool + DoesUnwindOnError () const + { + return m_unwind_on_error; + } + + EvaluateExpressionOptions& + SetUnwindOnError (bool unwind = false) + { + m_unwind_on_error = unwind; + return *this; + } + + bool + DoesIgnoreBreakpoints () const + { + return m_ignore_breakpoints; + } + + EvaluateExpressionOptions& + SetIgnoreBreakpoints (bool ignore = false) + { + m_ignore_breakpoints = ignore; + return *this; + } + + bool + DoesKeepInMemory () const + { + return m_keep_in_memory; + } + + EvaluateExpressionOptions& + SetKeepInMemory (bool keep = true) + { + m_keep_in_memory = keep; + return *this; + } + + lldb::DynamicValueType + GetUseDynamic () const + { + return m_use_dynamic; + } + + EvaluateExpressionOptions& + SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget) + { + m_use_dynamic = dynamic; + return *this; + } + + uint32_t + GetTimeoutUsec () const + { + return m_timeout_usec; + } + + EvaluateExpressionOptions& + SetTimeoutUsec (uint32_t timeout = 0) + { + m_timeout_usec = timeout; + return *this; + } + + bool + GetRunOthers () const + { + return m_run_others; + } + + EvaluateExpressionOptions& + SetRunOthers (bool run_others = true) + { + m_run_others = run_others; + return *this; + } + +private: + ExecutionPolicy m_execution_policy; + bool m_coerce_to_id; + bool m_unwind_on_error; + bool m_ignore_breakpoints; + bool m_keep_in_memory; + bool m_run_others; + lldb::DynamicValueType m_use_dynamic; + uint32_t m_timeout_usec; +}; + +//---------------------------------------------------------------------- +// Target +//---------------------------------------------------------------------- +class Target : + public std::enable_shared_from_this<Target>, + public TargetProperties, + public Broadcaster, + public ExecutionContextScope, + public ModuleList::Notifier +{ +public: + friend class TargetList; + + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + enum + { + eBroadcastBitBreakpointChanged = (1 << 0), + eBroadcastBitModulesLoaded = (1 << 1), + eBroadcastBitModulesUnloaded = (1 << 2), + eBroadcastBitWatchpointChanged = (1 << 3), + eBroadcastBitSymbolsLoaded = (1 << 4) + }; + + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + + // This event data class is for use by the TargetList to broadcast new target notifications. + class TargetEventData : public EventData + { + public: + + static const ConstString & + GetFlavorString (); + + virtual const ConstString & + GetFlavor () const; + + TargetEventData (const lldb::TargetSP &new_target_sp); + + lldb::TargetSP & + GetTarget() + { + return m_target_sp; + } + + virtual + ~TargetEventData(); + + virtual void + Dump (Stream *s) const; + + static const lldb::TargetSP + GetTargetFromEvent (const lldb::EventSP &event_sp); + + static const TargetEventData * + GetEventDataFromEvent (const Event *event_sp); + + private: + lldb::TargetSP m_target_sp; + + DISALLOW_COPY_AND_ASSIGN (TargetEventData); + }; + + static void + SettingsInitialize (); + + static void + SettingsTerminate (); + +// static lldb::UserSettingsControllerSP & +// GetSettingsController (); + + static FileSpecList + GetDefaultExecutableSearchPaths (); + + static FileSpecList + GetDefaultDebugFileSearchPaths (); + + static ArchSpec + GetDefaultArchitecture (); + + static void + SetDefaultArchitecture (const ArchSpec &arch); + +// void +// UpdateInstanceName (); + + lldb::ModuleSP + GetSharedModule (const ModuleSpec &module_spec, + Error *error_ptr = NULL); + + //---------------------------------------------------------------------- + // Settings accessors + //---------------------------------------------------------------------- + + static const TargetPropertiesSP & + GetGlobalProperties(); + + +private: + //------------------------------------------------------------------ + /// Construct with optional file and arch. + /// + /// This member is private. Clients must use + /// TargetList::CreateTarget(const FileSpec*, const ArchSpec*) + /// so all targets can be tracked from the central target list. + /// + /// @see TargetList::CreateTarget(const FileSpec*, const ArchSpec*) + //------------------------------------------------------------------ + Target (Debugger &debugger, + const ArchSpec &target_arch, + const lldb::PlatformSP &platform_sp); + + // Helper function. + bool + ProcessIsValid (); + +public: + ~Target(); + + Mutex & + GetAPIMutex () + { + return m_mutex; + } + + void + DeleteCurrentProcess (); + + void + CleanupProcess (); + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. The dumped content will be only what has + /// been loaded or parsed up to this point at which this function + /// is called, so this is a good way to see what has been parsed + /// in a target. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s, lldb::DescriptionLevel description_level); + + const lldb::ProcessSP & + CreateProcess (Listener &listener, + const char *plugin_name, + const FileSpec *crash_file); + + const lldb::ProcessSP & + GetProcessSP () const; + + bool + IsValid() + { + return m_valid; + } + + void + Destroy(); + + //------------------------------------------------------------------ + // This part handles the breakpoints. + //------------------------------------------------------------------ + + BreakpointList & + GetBreakpointList(bool internal = false); + + const BreakpointList & + GetBreakpointList(bool internal = false) const; + + lldb::BreakpointSP + GetLastCreatedBreakpoint () + { + return m_last_created_breakpoint; + } + + lldb::BreakpointSP + GetBreakpointByID (lldb::break_id_t break_id); + + // Use this to create a file and line breakpoint to a given module or all module it is NULL + lldb::BreakpointSP + CreateBreakpoint (const FileSpecList *containingModules, + const FileSpec &file, + uint32_t line_no, + LazyBool check_inlines = eLazyBoolCalculate, + LazyBool skip_prologue = eLazyBoolCalculate, + bool internal = false); + + // Use this to create breakpoint that matches regex against the source lines in files given in source_file_list: + lldb::BreakpointSP + CreateSourceRegexBreakpoint (const FileSpecList *containingModules, + const FileSpecList *source_file_list, + RegularExpression &source_regex, + bool internal = false); + + // Use this to create a breakpoint from a load address + lldb::BreakpointSP + CreateBreakpoint (lldb::addr_t load_addr, + bool internal = false); + + // Use this to create Address breakpoints: + lldb::BreakpointSP + CreateBreakpoint (Address &addr, + bool internal = false); + + // Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is NULL + // When "skip_prologue is set to eLazyBoolCalculate, we use the current target + // setting, else we use the values passed in + lldb::BreakpointSP + CreateFuncRegexBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, + RegularExpression &func_regexp, + LazyBool skip_prologue = eLazyBoolCalculate, + bool internal = false); + + // Use this to create a function breakpoint by name in containingModule, or all modules if it is NULL + // When "skip_prologue is set to eLazyBoolCalculate, we use the current target + // setting, else we use the values passed in + lldb::BreakpointSP + CreateBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, + const char *func_name, + uint32_t func_name_type_mask, + LazyBool skip_prologue = eLazyBoolCalculate, + bool internal = false); + + lldb::BreakpointSP + CreateExceptionBreakpoint (enum lldb::LanguageType language, bool catch_bp, bool throw_bp, bool internal = false); + + // This is the same as the func_name breakpoint except that you can specify a vector of names. This is cheaper + // than a regular expression breakpoint in the case where you just want to set a breakpoint on a set of names + // you already know. + lldb::BreakpointSP + CreateBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, + const char *func_names[], + size_t num_names, + uint32_t func_name_type_mask, + LazyBool skip_prologue = eLazyBoolCalculate, + bool internal = false); + + lldb::BreakpointSP + CreateBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, + const std::vector<std::string> &func_names, + uint32_t func_name_type_mask, + LazyBool skip_prologue = eLazyBoolCalculate, + bool internal = false); + + + // Use this to create a general breakpoint: + lldb::BreakpointSP + CreateBreakpoint (lldb::SearchFilterSP &filter_sp, + lldb::BreakpointResolverSP &resolver_sp, + bool internal = false); + + // Use this to create a watchpoint: + lldb::WatchpointSP + CreateWatchpoint (lldb::addr_t addr, + size_t size, + const ClangASTType *type, + uint32_t kind, + Error &error); + + lldb::WatchpointSP + GetLastCreatedWatchpoint () + { + return m_last_created_watchpoint; + } + + WatchpointList & + GetWatchpointList() + { + return m_watchpoint_list; + } + + void + RemoveAllBreakpoints (bool internal_also = false); + + void + DisableAllBreakpoints (bool internal_also = false); + + void + EnableAllBreakpoints (bool internal_also = false); + + bool + DisableBreakpointByID (lldb::break_id_t break_id); + + bool + EnableBreakpointByID (lldb::break_id_t break_id); + + bool + RemoveBreakpointByID (lldb::break_id_t break_id); + + // The flag 'end_to_end', default to true, signifies that the operation is + // performed end to end, for both the debugger and the debuggee. + + bool + RemoveAllWatchpoints (bool end_to_end = true); + + bool + DisableAllWatchpoints (bool end_to_end = true); + + bool + EnableAllWatchpoints (bool end_to_end = true); + + bool + ClearAllWatchpointHitCounts (); + + bool + IgnoreAllWatchpoints (uint32_t ignore_count); + + bool + DisableWatchpointByID (lldb::watch_id_t watch_id); + + bool + EnableWatchpointByID (lldb::watch_id_t watch_id); + + bool + RemoveWatchpointByID (lldb::watch_id_t watch_id); + + bool + IgnoreWatchpointByID (lldb::watch_id_t watch_id, uint32_t ignore_count); + + //------------------------------------------------------------------ + /// Get \a load_addr as a callable code load address for this target + /// + /// Take \a load_addr and potentially add any address bits that are + /// needed to make the address callable. For ARM this can set bit + /// zero (if it already isn't) if \a load_addr is a thumb function. + /// If \a addr_class is set to eAddressClassInvalid, then the address + /// adjustment will always happen. If it is set to an address class + /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be + /// returned. + //------------------------------------------------------------------ + lldb::addr_t + GetCallableLoadAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const; + + //------------------------------------------------------------------ + /// Get \a load_addr as an opcode for this target. + /// + /// Take \a load_addr and potentially strip any address bits that are + /// needed to make the address point to an opcode. For ARM this can + /// clear bit zero (if it already isn't) if \a load_addr is a + /// thumb function and load_addr is in code. + /// If \a addr_class is set to eAddressClassInvalid, then the address + /// adjustment will always happen. If it is set to an address class + /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be + /// returned. + //------------------------------------------------------------------ + lldb::addr_t + GetOpcodeLoadAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const; + +protected: + //------------------------------------------------------------------ + /// Implementing of ModuleList::Notifier. + //------------------------------------------------------------------ + + virtual void + ModuleAdded (const ModuleList& module_list, const lldb::ModuleSP& module_sp); + + virtual void + ModuleRemoved (const ModuleList& module_list, const lldb::ModuleSP& module_sp); + + virtual void + ModuleUpdated (const ModuleList& module_list, + const lldb::ModuleSP& old_module_sp, + const lldb::ModuleSP& new_module_sp); + virtual void + WillClearList (const ModuleList& module_list); + +public: + + void + ModulesDidLoad (ModuleList &module_list); + + void + ModulesDidUnload (ModuleList &module_list); + + void + SymbolsDidLoad (ModuleList &module_list); + + //------------------------------------------------------------------ + /// Gets the module for the main executable. + /// + /// Each process has a notion of a main executable that is the file + /// that will be executed or attached to. Executable files can have + /// dependent modules that are discovered from the object files, or + /// discovered at runtime as things are dynamically loaded. + /// + /// @return + /// The shared pointer to the executable module which can + /// contains a NULL Module object if no executable has been + /// set. + /// + /// @see DynamicLoader + /// @see ObjectFile::GetDependentModules (FileSpecList&) + /// @see Process::SetExecutableModule(lldb::ModuleSP&) + //------------------------------------------------------------------ + lldb::ModuleSP + GetExecutableModule (); + + Module* + GetExecutableModulePointer (); + + //------------------------------------------------------------------ + /// Set the main executable module. + /// + /// Each process has a notion of a main executable that is the file + /// that will be executed or attached to. Executable files can have + /// dependent modules that are discovered from the object files, or + /// discovered at runtime as things are dynamically loaded. + /// + /// Setting the executable causes any of the current dependant + /// image information to be cleared and replaced with the static + /// dependent image information found by calling + /// ObjectFile::GetDependentModules (FileSpecList&) on the main + /// executable and any modules on which it depends. Calling + /// Process::GetImages() will return the newly found images that + /// were obtained from all of the object files. + /// + /// @param[in] module_sp + /// A shared pointer reference to the module that will become + /// the main executable for this process. + /// + /// @param[in] get_dependent_files + /// If \b true then ask the object files to track down any + /// known dependent files. + /// + /// @see ObjectFile::GetDependentModules (FileSpecList&) + /// @see Process::GetImages() + //------------------------------------------------------------------ + void + SetExecutableModule (lldb::ModuleSP& module_sp, bool get_dependent_files); + + bool + LoadScriptingResources (std::list<Error>& errors, + Stream* feedback_stream = NULL, + bool continue_on_error = true) + { + return m_images.LoadScriptingResourcesInTarget(this,errors,feedback_stream,continue_on_error); + } + + //------------------------------------------------------------------ + /// Get accessor for the images for this process. + /// + /// Each process has a notion of a main executable that is the file + /// that will be executed or attached to. Executable files can have + /// dependent modules that are discovered from the object files, or + /// discovered at runtime as things are dynamically loaded. After + /// a main executable has been set, the images will contain a list + /// of all the files that the executable depends upon as far as the + /// object files know. These images will usually contain valid file + /// virtual addresses only. When the process is launched or attached + /// to, the DynamicLoader plug-in will discover where these images + /// were loaded in memory and will resolve the load virtual + /// addresses is each image, and also in images that are loaded by + /// code. + /// + /// @return + /// A list of Module objects in a module list. + //------------------------------------------------------------------ + const ModuleList& + GetImages () const + { + return m_images; + } + + ModuleList& + GetImages () + { + return m_images; + } + + //------------------------------------------------------------------ + /// Return whether this FileSpec corresponds to a module that should be considered for general searches. + /// + /// This API will be consulted by the SearchFilterForNonModuleSpecificSearches + /// and any module that returns \b true will not be searched. Note the + /// SearchFilterForNonModuleSpecificSearches is the search filter that + /// gets used in the CreateBreakpoint calls when no modules is provided. + /// + /// The target call at present just consults the Platform's call of the + /// same name. + /// + /// @param[in] module_sp + /// A shared pointer reference to the module that checked. + /// + /// @return \b true if the module should be excluded, \b false otherwise. + //------------------------------------------------------------------ + bool + ModuleIsExcludedForNonModuleSpecificSearches (const FileSpec &module_spec); + + //------------------------------------------------------------------ + /// Return whether this module should be considered for general searches. + /// + /// This API will be consulted by the SearchFilterForNonModuleSpecificSearches + /// and any module that returns \b true will not be searched. Note the + /// SearchFilterForNonModuleSpecificSearches is the search filter that + /// gets used in the CreateBreakpoint calls when no modules is provided. + /// + /// The target call at present just consults the Platform's call of the + /// same name. + /// + /// FIXME: When we get time we should add a way for the user to set modules that they + /// don't want searched, in addition to or instead of the platform ones. + /// + /// @param[in] module_sp + /// A shared pointer reference to the module that checked. + /// + /// @return \b true if the module should be excluded, \b false otherwise. + //------------------------------------------------------------------ + bool + ModuleIsExcludedForNonModuleSpecificSearches (const lldb::ModuleSP &module_sp); + + ArchSpec & + GetArchitecture () + { + return m_arch; + } + + const ArchSpec & + GetArchitecture () const + { + return m_arch; + } + + //------------------------------------------------------------------ + /// Set the architecture for this target. + /// + /// If the current target has no Images read in, then this just sets the architecture, which will + /// be used to select the architecture of the ExecutableModule when that is set. + /// If the current target has an ExecutableModule, then calling SetArchitecture with a different + /// architecture from the currently selected one will reset the ExecutableModule to that slice + /// of the file backing the ExecutableModule. If the file backing the ExecutableModule does not + /// contain a fork of this architecture, then this code will return false, and the architecture + /// won't be changed. + /// If the input arch_spec is the same as the already set architecture, this is a no-op. + /// + /// @param[in] arch_spec + /// The new architecture. + /// + /// @return + /// \b true if the architecture was successfully set, \bfalse otherwise. + //------------------------------------------------------------------ + bool + SetArchitecture (const ArchSpec &arch_spec); + + Debugger & + GetDebugger () + { + return m_debugger; + } + + size_t + ReadMemoryFromFileCache (const Address& addr, + void *dst, + size_t dst_len, + Error &error); + + // Reading memory through the target allows us to skip going to the process + // for reading memory if possible and it allows us to try and read from + // any constant sections in our object files on disk. If you always want + // live program memory, read straight from the process. If you possibly + // want to read from const sections in object files, read from the target. + // This version of ReadMemory will try and read memory from the process + // if the process is alive. The order is: + // 1 - if (prefer_file_cache == true) then read from object file cache + // 2 - if there is a valid process, try and read from its memory + // 3 - if (prefer_file_cache == false) then read from object file cache + size_t + ReadMemory (const Address& addr, + bool prefer_file_cache, + void *dst, + size_t dst_len, + Error &error, + lldb::addr_t *load_addr_ptr = NULL); + + size_t + ReadCStringFromMemory (const Address& addr, std::string &out_str, Error &error); + + size_t + ReadCStringFromMemory (const Address& addr, char *dst, size_t dst_max_len, Error &result_error); + + size_t + ReadScalarIntegerFromMemory (const Address& addr, + bool prefer_file_cache, + uint32_t byte_size, + bool is_signed, + Scalar &scalar, + Error &error); + + uint64_t + ReadUnsignedIntegerFromMemory (const Address& addr, + bool prefer_file_cache, + size_t integer_byte_size, + uint64_t fail_value, + Error &error); + + bool + ReadPointerFromMemory (const Address& addr, + bool prefer_file_cache, + Error &error, + Address &pointer_addr); + + SectionLoadList& + GetSectionLoadList() + { + return m_section_load_list; + } + + const SectionLoadList& + GetSectionLoadList() const + { + return m_section_load_list; + } + + static Target * + GetTargetFromContexts (const ExecutionContext *exe_ctx_ptr, + const SymbolContext *sc_ptr); + + //------------------------------------------------------------------ + // lldb::ExecutionContextScope pure virtual functions + //------------------------------------------------------------------ + virtual lldb::TargetSP + CalculateTarget (); + + virtual lldb::ProcessSP + CalculateProcess (); + + virtual lldb::ThreadSP + CalculateThread (); + + virtual lldb::StackFrameSP + CalculateStackFrame (); + + virtual void + CalculateExecutionContext (ExecutionContext &exe_ctx); + + PathMappingList & + GetImageSearchPathList (); + + ClangASTContext * + GetScratchClangASTContext(bool create_on_demand=true); + + ClangASTImporter * + GetClangASTImporter(); + + + // Since expressions results can persist beyond the lifetime of a process, + // and the const expression results are available after a process is gone, + // we provide a way for expressions to be evaluated from the Target itself. + // If an expression is going to be run, then it should have a frame filled + // in in th execution context. + ExecutionResults + EvaluateExpression (const char *expression, + StackFrame *frame, + lldb::ValueObjectSP &result_valobj_sp, + const EvaluateExpressionOptions& options = EvaluateExpressionOptions()); + + ClangPersistentVariables & + GetPersistentVariables() + { + return m_persistent_variables; + } + + //------------------------------------------------------------------ + // Target Stop Hooks + //------------------------------------------------------------------ + class StopHook : public UserID + { + public: + ~StopHook (); + + StopHook (const StopHook &rhs); + + StringList * + GetCommandPointer () + { + return &m_commands; + } + + const StringList & + GetCommands() + { + return m_commands; + } + + lldb::TargetSP & + GetTarget() + { + return m_target_sp; + } + + void + SetCommands (StringList &in_commands) + { + m_commands = in_commands; + } + + // Set the specifier. The stop hook will own the specifier, and is responsible for deleting it when we're done. + void + SetSpecifier (SymbolContextSpecifier *specifier) + { + m_specifier_sp.reset (specifier); + } + + SymbolContextSpecifier * + GetSpecifier () + { + return m_specifier_sp.get(); + } + + // Set the Thread Specifier. The stop hook will own the thread specifier, and is responsible for deleting it when we're done. + void + SetThreadSpecifier (ThreadSpec *specifier); + + ThreadSpec * + GetThreadSpecifier() + { + return m_thread_spec_ap.get(); + } + + bool + IsActive() + { + return m_active; + } + + void + SetIsActive (bool is_active) + { + m_active = is_active; + } + + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + + private: + lldb::TargetSP m_target_sp; + StringList m_commands; + lldb::SymbolContextSpecifierSP m_specifier_sp; + std::unique_ptr<ThreadSpec> m_thread_spec_ap; + bool m_active; + + // Use AddStopHook to make a new empty stop hook. The GetCommandPointer and fill it with commands, + // and SetSpecifier to set the specifier shared pointer (can be null, that will match anything.) + StopHook (lldb::TargetSP target_sp, lldb::user_id_t uid); + friend class Target; + }; + typedef std::shared_ptr<StopHook> StopHookSP; + + // Add an empty stop hook to the Target's stop hook list, and returns a shared pointer to it in new_hook. + // Returns the id of the new hook. + lldb::user_id_t + AddStopHook (StopHookSP &new_hook); + + void + RunStopHooks (); + + size_t + GetStopHookSize(); + + bool + SetSuppresStopHooks (bool suppress) + { + bool old_value = m_suppress_stop_hooks; + m_suppress_stop_hooks = suppress; + return old_value; + } + + bool + GetSuppressStopHooks () + { + return m_suppress_stop_hooks; + } + + bool + SetSuppressSyntheticValue (bool suppress) + { + bool old_value = m_suppress_synthetic_value; + m_suppress_synthetic_value = suppress; + return old_value; + } + + bool + GetSuppressSyntheticValue () + { + return m_suppress_synthetic_value; + } + +// StopHookSP & +// GetStopHookByIndex (size_t index); +// + bool + RemoveStopHookByID (lldb::user_id_t uid); + + void + RemoveAllStopHooks (); + + StopHookSP + GetStopHookByID (lldb::user_id_t uid); + + bool + SetStopHookActiveStateByID (lldb::user_id_t uid, bool active_state); + + void + SetAllStopHooksActiveState (bool active_state); + + size_t GetNumStopHooks () const + { + return m_stop_hooks.size(); + } + + StopHookSP + GetStopHookAtIndex (size_t index) + { + if (index >= GetNumStopHooks()) + return StopHookSP(); + StopHookCollection::iterator pos = m_stop_hooks.begin(); + + while (index > 0) + { + pos++; + index--; + } + return (*pos).second; + } + + lldb::PlatformSP + GetPlatform () + { + return m_platform_sp; + } + + void + SetPlatform (const lldb::PlatformSP &platform_sp) + { + m_platform_sp = platform_sp; + } + + SourceManager & + GetSourceManager (); + + //------------------------------------------------------------------ + // Methods. + //------------------------------------------------------------------ + lldb::SearchFilterSP + GetSearchFilterForModule (const FileSpec *containingModule); + + lldb::SearchFilterSP + GetSearchFilterForModuleList (const FileSpecList *containingModuleList); + + lldb::SearchFilterSP + GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles); + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + Debugger & m_debugger; + lldb::PlatformSP m_platform_sp; ///< The platform for this target. + Mutex m_mutex; ///< An API mutex that is used by the lldb::SB* classes make the SB interface thread safe + ArchSpec m_arch; + ModuleList m_images; ///< The list of images for this process (shared libraries and anything dynamically loaded). + SectionLoadList m_section_load_list; + BreakpointList m_breakpoint_list; + BreakpointList m_internal_breakpoint_list; + lldb::BreakpointSP m_last_created_breakpoint; + WatchpointList m_watchpoint_list; + lldb::WatchpointSP m_last_created_watchpoint; + // We want to tightly control the process destruction process so + // we can correctly tear down everything that we need to, so the only + // class that knows about the process lifespan is this target class. + lldb::ProcessSP m_process_sp; + bool m_valid; + lldb::SearchFilterSP m_search_filter_sp; + PathMappingList m_image_search_paths; + std::unique_ptr<ClangASTContext> m_scratch_ast_context_ap; + std::unique_ptr<ClangASTSource> m_scratch_ast_source_ap; + std::unique_ptr<ClangASTImporter> m_ast_importer_ap; + ClangPersistentVariables m_persistent_variables; ///< These are the persistent variables associated with this process for the expression parser. + + std::unique_ptr<SourceManager> m_source_manager_ap; + + typedef std::map<lldb::user_id_t, StopHookSP> StopHookCollection; + StopHookCollection m_stop_hooks; + lldb::user_id_t m_stop_hook_next_id; + bool m_suppress_stop_hooks; + bool m_suppress_synthetic_value; + + static void + ImageSearchPathsChanged (const PathMappingList &path_list, + void *baton); + +private: + DISALLOW_COPY_AND_ASSIGN (Target); +}; + +} // namespace lldb_private + +#endif // liblldb_Target_h_ diff --git a/include/lldb/Target/TargetList.h b/include/lldb/Target/TargetList.h new file mode 100644 index 0000000..41404e1 --- /dev/null +++ b/include/lldb/Target/TargetList.h @@ -0,0 +1,239 @@ +//===-- TargetList.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_TargetList_h_ +#define liblldb_TargetList_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/Broadcaster.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/Target.h" + +namespace lldb_private { + +class TargetList : public Broadcaster +{ +private: + friend class Debugger; + + //------------------------------------------------------------------ + /// Constructor + /// + /// The constructor for the target list is private. Clients can + /// get ahold of of the one and only target list through the + /// lldb_private::Debugger::GetSharedInstance().GetTargetList(). + /// + /// @see static TargetList& lldb_private::Debugger::GetTargetList(). + //------------------------------------------------------------------ + TargetList(Debugger &debugger); + +public: + + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + enum + { + eBroadcastBitInterrupt = (1 << 0) + }; + + + // These two functions fill out the Broadcaster interface: + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + + virtual ~TargetList(); + + //------------------------------------------------------------------ + /// Create a new Target. + /// + /// Clients must use this function to create a Target. This allows + /// a global list of targets to be maintained in a central location + /// so signal handlers and other global functions can use it to + /// locate an appropriate target to deliver asynchronous information + /// to. + /// + /// @param[in] debugger + /// The debugger to associate this target with + /// + /// @param[in] file_spec + /// The main executable file for a debug target. This value + /// can be NULL and the file can be set later using: + /// Target::SetExecutableModule (ModuleSP&) + /// + /// @param[in] triple_cstr + /// A target triple string to be used for the target. This can + /// be NULL if the triple is not known or when attaching to a + /// process. + /// + /// @param[in] get_dependent_modules + /// Track down the dependent modules for an executable and + /// load those into the module list. + /// + /// @param[in] platform_options + /// A pointer to the platform options to use when creating this + /// target. If this value is NULL, then the currently selected + /// platform will be used. + /// + /// @param[out] target_sp + /// A shared pointer to a target that will be filled in if + /// this call is successful. + /// + /// @return + /// An error object that indicates success or failure + //------------------------------------------------------------------ + Error + CreateTarget (Debugger &debugger, + const char *user_exe_path, + const char *triple_cstr, + bool get_dependent_modules, + const OptionGroupPlatform *platform_options, + lldb::TargetSP &target_sp); + + //------------------------------------------------------------------ + /// Create a new Target. + /// + /// Same as the function above, but used when you already know the + /// platform you will be using + //------------------------------------------------------------------ + Error + CreateTarget (Debugger &debugger, + const char *user_exe_path, + const ArchSpec& arch, + bool get_dependent_modules, + lldb::PlatformSP &platform_sp, + lldb::TargetSP &target_sp); + + //------------------------------------------------------------------ + /// Delete a Target object from the list. + /// + /// When clients are done with the Target objets, this function + /// should be called to release the memory associated with a target + /// object. + /// + /// @param[in] target_sp + /// The shared pointer to a target. + /// + /// @return + /// Returns \b true if the target was successfully removed from + /// from this target list, \b false otherwise. The client will + /// be left with the last remaining shared pointer to the target + /// in \a target_sp which can then be properly released. + //------------------------------------------------------------------ + bool + DeleteTarget (lldb::TargetSP &target_sp); + + int + GetNumTargets () const; + + lldb::TargetSP + GetTargetAtIndex (uint32_t index) const; + + uint32_t + GetIndexOfTarget (lldb::TargetSP target_sp) const; + + //------------------------------------------------------------------ + /// Find the target that contains has an executable whose path + /// matches \a exe_file_spec, and whose architecture matches + /// \a arch_ptr if arch_ptr is not NULL. + /// + /// @param[in] exe_file_spec + /// A file spec containing a basename, or a full path (directory + /// and basename). If \a exe_file_spec contains only a filename + /// (empty GetDirectory() value) then matching will be done + /// solely based on the filenames and directories won't be + /// compared. If \a exe_file_spec contains a filename and a + /// directory, then both must match. + /// + /// @param[in] exe_arch_ptr + /// If not NULL then the architecture also needs to match, else + /// the architectures will be compared. + /// + /// @return + /// A shared pointer to a target object. The returned shared + /// pointer will contain NULL if no target objects have a + /// executable whose full or partial path matches + /// with a matching process ID. + //------------------------------------------------------------------ + lldb::TargetSP + FindTargetWithExecutableAndArchitecture (const FileSpec &exe_file_spec, + const ArchSpec *exe_arch_ptr = NULL) const; + + //------------------------------------------------------------------ + /// Find the target that contains a process with process ID \a + /// pid. + /// + /// @param[in] pid + /// The process ID to search our target list for. + /// + /// @return + /// A shared pointer to a target object. The returned shared + /// pointer will contain NULL if no target objects own a process + /// with a matching process ID. + //------------------------------------------------------------------ + lldb::TargetSP + FindTargetWithProcessID (lldb::pid_t pid) const; + + lldb::TargetSP + FindTargetWithProcess (lldb_private::Process *process) const; + + lldb::TargetSP + GetTargetSP (Target *target) const; + + //------------------------------------------------------------------ + /// Send an async interrupt to one or all processes. + /// + /// Find the target that contains the process with process ID \a + /// pid and send a LLDB_EVENT_ASYNC_INTERRUPT event to the process's + /// event queue. + /// + /// @param[in] pid + /// The process ID to search our target list for, if \a pid is + /// LLDB_INVALID_PROCESS_ID, then the interrupt will be sent to + /// all processes. + /// + /// @return + /// The number of async interrupts sent. + //------------------------------------------------------------------ + uint32_t + SendAsyncInterrupt (lldb::pid_t pid = LLDB_INVALID_PROCESS_ID); + + uint32_t + SignalIfRunning (lldb::pid_t pid, int signo); + + uint32_t + SetSelectedTarget (Target *target); + + lldb::TargetSP + GetSelectedTarget (); + + +protected: + typedef std::vector<lldb::TargetSP> collection; + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + collection m_target_list; + mutable Mutex m_target_list_mutex; + uint32_t m_selected_target_idx; +private: + DISALLOW_COPY_AND_ASSIGN (TargetList); +}; + +} // namespace lldb_private + +#endif // liblldb_TargetList_h_ diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h new file mode 100644 index 0000000..e4e532e --- /dev/null +++ b/include/lldb/Target/Thread.h @@ -0,0 +1,1067 @@ +//===-- Thread.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_Thread_h_ +#define liblldb_Thread_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Event.h" +#include "lldb/Core/UserID.h" +#include "lldb/Core/UserSettingsController.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/StackFrameList.h" + +#define LLDB_THREAD_MAX_STOP_EXC_DATA 8 + +namespace lldb_private { + +class ThreadProperties : public Properties +{ +public: + ThreadProperties(bool is_global); + + virtual + ~ThreadProperties(); + + //------------------------------------------------------------------ + /// The regular expression returned determines symbols that this + /// thread won't stop in during "step-in" operations. + /// + /// @return + /// A pointer to a regular expression to compare against symbols, + /// or NULL if all symbols are allowed. + /// + //------------------------------------------------------------------ + const RegularExpression * + GetSymbolsToAvoidRegexp(); + + bool + GetTraceEnabledState() const; +}; + +typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP; + +class Thread : + public std::enable_shared_from_this<Thread>, + public ThreadProperties, + public UserID, + public ExecutionContextScope, + public Broadcaster +{ +public: + //------------------------------------------------------------------ + /// Broadcaster event bits definitions. + //------------------------------------------------------------------ + enum + { + eBroadcastBitStackChanged = (1 << 0), + eBroadcastBitThreadSuspended = (1 << 1), + eBroadcastBitThreadResumed = (1 << 2), + eBroadcastBitSelectedFrameChanged = (1 << 3), + eBroadcastBitThreadSelected = (1 << 4) + }; + + static ConstString &GetStaticBroadcasterClass (); + + virtual ConstString &GetBroadcasterClass() const + { + return GetStaticBroadcasterClass(); + } + + class ThreadEventData : + public EventData + { + public: + ThreadEventData (const lldb::ThreadSP thread_sp); + + ThreadEventData (const lldb::ThreadSP thread_sp, const StackID &stack_id); + + ThreadEventData(); + + virtual ~ThreadEventData(); + + static const ConstString & + GetFlavorString (); + + virtual const ConstString & + GetFlavor () const + { + return ThreadEventData::GetFlavorString (); + } + + virtual void + Dump (Stream *s) const; + + static const ThreadEventData * + GetEventDataFromEvent (const Event *event_ptr); + + static lldb::ThreadSP + GetThreadFromEvent (const Event *event_ptr); + + static StackID + GetStackIDFromEvent (const Event *event_ptr); + + static lldb::StackFrameSP + GetStackFrameFromEvent (const Event *event_ptr); + + lldb::ThreadSP + GetThread () const + { + return m_thread_sp; + } + + StackID + GetStackID () const + { + return m_stack_id; + } + + private: + lldb::ThreadSP m_thread_sp; + StackID m_stack_id; + DISALLOW_COPY_AND_ASSIGN (ThreadEventData); + }; + + // TODO: You shouldn't just checkpoint the register state alone, so this should get + // moved to protected. To do that ThreadStateCheckpoint needs to be returned as a token... + class RegisterCheckpoint + { + public: + + RegisterCheckpoint() : + m_stack_id (), + m_data_sp () + { + } + + RegisterCheckpoint (const StackID &stack_id) : + m_stack_id (stack_id), + m_data_sp () + { + } + + ~RegisterCheckpoint() + { + } + + const RegisterCheckpoint& + operator= (const RegisterCheckpoint &rhs) + { + if (this != &rhs) + { + this->m_stack_id = rhs.m_stack_id; + this->m_data_sp = rhs.m_data_sp; + } + return *this; + } + + RegisterCheckpoint (const RegisterCheckpoint &rhs) : + m_stack_id (rhs.m_stack_id), + m_data_sp (rhs.m_data_sp) + { + } + + const StackID & + GetStackID() + { + return m_stack_id; + } + + void + SetStackID (const StackID &stack_id) + { + m_stack_id = stack_id; + } + + lldb::DataBufferSP & + GetData() + { + return m_data_sp; + } + + const lldb::DataBufferSP & + GetData() const + { + return m_data_sp; + } + + protected: + StackID m_stack_id; + lldb::DataBufferSP m_data_sp; + }; + + struct ThreadStateCheckpoint + { + uint32_t orig_stop_id; // Dunno if I need this yet but it is an interesting bit of data. + lldb::StopInfoSP stop_info_sp; // You have to restore the stop info or you might continue with the wrong signals. + RegisterCheckpoint register_backup; // You need to restore the registers, of course... + uint32_t current_inlined_depth; + lldb::addr_t current_inlined_pc; + }; + + static void + SettingsInitialize (); + + static void + SettingsTerminate (); + + static const ThreadPropertiesSP & + GetGlobalProperties(); + + Thread (Process &process, lldb::tid_t tid); + virtual ~Thread(); + + lldb::ProcessSP + GetProcess() const + { + return m_process_wp.lock(); + } + + int + GetResumeSignal () const + { + return m_resume_signal; + } + + void + SetResumeSignal (int signal) + { + m_resume_signal = signal; + } + + lldb::StateType + GetState() const; + + void + SetState (lldb::StateType state); + + lldb::StateType + GetResumeState () const + { + return m_resume_state; + } + + void + SetResumeState (lldb::StateType state) + { + m_resume_state = state; + } + + // This function is called on all the threads before "ShouldResume" and + // "WillResume" in case a thread needs to change its state before the + // ThreadList polls all the threads to figure out which ones actually + // will get to run and how. + void + SetupForResume (); + + // Do not override this function, it is for thread plan logic only + bool + ShouldResume (lldb::StateType resume_state); + + // Override this to do platform specific tasks before resume. + virtual void + WillResume (lldb::StateType resume_state) + { + } + + // This clears generic thread state after a resume. If you subclass this, + // be sure to call it. + virtual void + DidResume (); + + // This notifies the thread when a private stop occurs. + virtual void + DidStop (); + + virtual void + RefreshStateAfterStop() = 0; + + void + WillStop (); + + bool + ShouldStop (Event *event_ptr); + + Vote + ShouldReportStop (Event *event_ptr); + + Vote + ShouldReportRun (Event *event_ptr); + + void + Flush (); + + // Return whether this thread matches the specification in ThreadSpec. This is a virtual + // method because at some point we may extend the thread spec with a platform specific + // dictionary of attributes, which then only the platform specific Thread implementation + // would know how to match. For now, this just calls through to the ThreadSpec's + // ThreadPassesBasicTests method. + virtual bool + MatchesSpec (const ThreadSpec *spec); + + lldb::StopInfoSP + GetStopInfo (); + + lldb::StopReason + GetStopReason(); + + // This sets the stop reason to a "blank" stop reason, so you can call functions on the thread + // without having the called function run with whatever stop reason you stopped with. + void + SetStopInfoToNothing(); + + bool + ThreadStoppedForAReason (); + + static const char * + RunModeAsCString (lldb::RunMode mode); + + static const char * + StopReasonAsCString (lldb::StopReason reason); + + virtual const char * + GetInfo () + { + return NULL; + } + + virtual const char * + GetName () + { + return NULL; + } + + virtual const char * + GetQueueName () + { + return NULL; + } + + virtual uint32_t + GetStackFrameCount() + { + return GetStackFrameList()->GetNumFrames(); + } + + virtual lldb::StackFrameSP + GetStackFrameAtIndex (uint32_t idx) + { + return GetStackFrameList()->GetFrameAtIndex(idx); + } + + virtual lldb::StackFrameSP + GetFrameWithConcreteFrameIndex (uint32_t unwind_idx); + + bool + DecrementCurrentInlinedDepth() + { + return GetStackFrameList()->DecrementCurrentInlinedDepth(); + } + + uint32_t + GetCurrentInlinedDepth() + { + return GetStackFrameList()->GetCurrentInlinedDepth(); + } + + Error + ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp, bool broadcast = false); + + Error + ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false); + + virtual lldb::StackFrameSP + GetFrameWithStackID (const StackID &stack_id) + { + if (stack_id.IsValid()) + return GetStackFrameList()->GetFrameWithStackID (stack_id); + return lldb::StackFrameSP(); + } + + uint32_t + GetSelectedFrameIndex () + { + return GetStackFrameList()->GetSelectedFrameIndex(); + } + + lldb::StackFrameSP + GetSelectedFrame () + { + lldb::StackFrameListSP stack_frame_list_sp(GetStackFrameList()); + return stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex()); + } + + uint32_t + SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false); + + + bool + SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast = false); + + bool + SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_stream); + + void + SetDefaultFileAndLineToSelectedFrame() + { + GetStackFrameList()->SetDefaultFileAndLineToSelectedFrame(); + } + + virtual lldb::RegisterContextSP + GetRegisterContext () = 0; + + virtual lldb::RegisterContextSP + CreateRegisterContextForFrame (StackFrame *frame) = 0; + + virtual void + ClearStackFrames (); + + virtual bool + SetBackingThread (const lldb::ThreadSP &thread_sp) + { + return false; + } + + virtual lldb::ThreadSP + GetBackingThread () const + { + return lldb::ThreadSP(); + } + + virtual void + ClearBackingThread () + { + // Subclasses can use this function if a thread is actually backed by + // another thread. This is currently used for the OperatingSystem plug-ins + // where they might have a thread that is in memory, yet its registers + // are available through the lldb_private::Thread subclass for the current + // lldb_private::Process class. Since each time the process stops the backing + // threads for memory threads can change, we need a way to clear the backing + // thread for all memory threads each time we stop. + } + + void + DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx); + + //------------------------------------------------------------------ + // Thread Plan Providers: + // This section provides the basic thread plans that the Process control + // machinery uses to run the target. ThreadPlan.h provides more details on + // how this mechanism works. + // The thread provides accessors to a set of plans that perform basic operations. + // The idea is that particular Platform plugins can override these methods to + // provide the implementation of these basic operations appropriate to their + // environment. + // + // NB: All the QueueThreadPlanXXX providers return Shared Pointers to + // Thread plans. This is useful so that you can modify the plans after + // creation in ways specific to that plan type. Also, it is often necessary for + // ThreadPlans that utilize other ThreadPlans to implement their task to keep a shared + // pointer to the sub-plan. + // But besides that, the shared pointers should only be held onto by entities who live no longer + // than the thread containing the ThreadPlan. + // FIXME: If this becomes a problem, we can make a version that just returns a pointer, + // which it is clearly unsafe to hold onto, and a shared pointer version, and only allow + // ThreadPlan and Co. to use the latter. That is made more annoying to do because there's + // no elegant way to friend a method to all sub-classes of a given class. + // + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Queues the base plan for a thread. + /// The version returned by Process does some things that are useful, + /// like handle breakpoints and signals, so if you return a plugin specific + /// one you probably want to call through to the Process one for anything + /// your plugin doesn't explicitly handle. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueFundamentalPlan (bool abort_other_plans); + + //------------------------------------------------------------------ + /// Queues the plan used to step over a breakpoint at the current PC of \a thread. + /// The default version returned by Process handles trap based breakpoints, and + /// will disable the breakpoint, single step over it, then re-enable it. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans); + + //------------------------------------------------------------------ + /// Queues the plan used to step one instruction from the current PC of \a thread. + /// + /// @param[in] step_over + /// \b true if we step over calls to functions, false if we step in. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @param[in] stop_other_threads + /// \b true if we will stop other threads while we single step this one. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepSingleInstruction (bool step_over, + bool abort_other_plans, + bool stop_other_threads); + + //------------------------------------------------------------------ + /// Queues the plan used to step through an address range, stepping over + /// function calls. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @param[in] type + /// Type of step to do, only eStepTypeInto and eStepTypeOver are supported by this plan. + /// + /// @param[in] range + /// The address range to step through. + /// + /// @param[in] addr_context + /// When dealing with stepping through inlined functions the current PC is not enough information to know + /// what "step" means. For instance a series of nested inline functions might start at the same address. + // The \a addr_context provides the current symbol context the step + /// is supposed to be out of. + // FIXME: Currently unused. + /// + /// @param[in] stop_other_threads + /// \b true if we will stop other threads while we single step this one. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepOverRange (bool abort_other_plans, + const AddressRange &range, + const SymbolContext &addr_context, + lldb::RunMode stop_other_threads); + + //------------------------------------------------------------------ + /// Queues the plan used to step through an address range, stepping into functions. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @param[in] type + /// Type of step to do, only eStepTypeInto and eStepTypeOver are supported by this plan. + /// + /// @param[in] range + /// The address range to step through. + /// + /// @param[in] addr_context + /// When dealing with stepping through inlined functions the current PC is not enough information to know + /// what "step" means. For instance a series of nested inline functions might start at the same address. + // The \a addr_context provides the current symbol context the step + /// is supposed to be out of. + // FIXME: Currently unused. + /// + /// @param[in] step_in_target + /// Name if function we are trying to step into. We will step out if we don't land in that function. + /// + /// @param[in] stop_other_threads + /// \b true if we will stop other threads while we single step this one. + /// + /// @param[in] avoid_code_without_debug_info + /// If \b true we will step out if we step into code with no debug info. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepInRange (bool abort_other_plans, + const AddressRange &range, + const SymbolContext &addr_context, + const char *step_in_target, + lldb::RunMode stop_other_threads, + bool avoid_code_without_debug_info); + + //------------------------------------------------------------------ + /// Queue the plan used to step out of the function at the current PC of + /// \a thread. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @param[in] addr_context + /// When dealing with stepping through inlined functions the current PC is not enough information to know + /// what "step" means. For instance a series of nested inline functions might start at the same address. + // The \a addr_context provides the current symbol context the step + /// is supposed to be out of. + // FIXME: Currently unused. + /// + /// @param[in] first_insn + /// \b true if this is the first instruction of a function. + /// + /// @param[in] stop_other_threads + /// \b true if we will stop other threads while we single step this one. + /// + /// @param[in] stop_vote + /// @param[in] run_vote + /// See standard meanings for the stop & run votes in ThreadPlan.h. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepOut (bool abort_other_plans, + SymbolContext *addr_context, + bool first_insn, + bool stop_other_threads, + Vote stop_vote, // = eVoteYes, + Vote run_vote, // = eVoteNoOpinion); + uint32_t frame_idx); + + //------------------------------------------------------------------ + /// Gets the plan used to step through the code that steps from a function + /// call site at the current PC into the actual function call. + /// + /// + /// @param[in] return_stack_id + /// The stack id that we will return to (by setting backstop breakpoints on the return + /// address to that frame) if we fail to step through. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @param[in] stop_other_threads + /// \b true if we will stop other threads while we single step this one. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepThrough (StackID &return_stack_id, + bool abort_other_plans, + bool stop_other_threads); + + //------------------------------------------------------------------ + /// Gets the plan used to continue from the current PC. + /// This is a simple plan, mostly useful as a backstop when you are continuing + /// for some particular purpose. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @param[in] target_addr + /// The address to which we're running. + /// + /// @param[in] stop_other_threads + /// \b true if we will stop other threads while we single step this one. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. + //------------------------------------------------------------------ + virtual lldb::ThreadPlanSP + QueueThreadPlanForRunToAddress (bool abort_other_plans, + Address &target_addr, + bool stop_other_threads); + + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepUntil (bool abort_other_plans, + lldb::addr_t *address_list, + size_t num_addresses, + bool stop_others, + uint32_t frame_idx); + + virtual lldb::ThreadPlanSP + QueueThreadPlanForCallFunction (bool abort_other_plans, + Address& function, + lldb::addr_t arg, + bool stop_other_threads, + bool unwind_on_error = false, + bool ignore_breakpoints = true); + + //------------------------------------------------------------------ + // Thread Plan accessors: + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Gets the plan which will execute next on the plan stack. + /// + /// @return + /// A pointer to the next executed plan. + //------------------------------------------------------------------ + ThreadPlan * + GetCurrentPlan (); + + //------------------------------------------------------------------ + /// Unwinds the thread stack for the innermost expression plan currently + /// on the thread plan stack. + /// + /// @return + /// An error if the thread plan could not be unwound. + //------------------------------------------------------------------ + + Error + UnwindInnermostExpression(); + +private: + bool + PlanIsBasePlan (ThreadPlan *plan_ptr); + + void + BroadcastSelectedFrameChange(StackID &new_frame_id); + +public: + + //------------------------------------------------------------------ + /// Gets the outer-most plan that was popped off the plan stack in the + /// most recent stop. Useful for printing the stop reason accurately. + /// + /// @return + /// A pointer to the last completed plan. + //------------------------------------------------------------------ + lldb::ThreadPlanSP + GetCompletedPlan (); + + //------------------------------------------------------------------ + /// Gets the outer-most return value from the completed plans + /// + /// @return + /// A ValueObjectSP, either empty if there is no return value, + /// or containing the return value. + //------------------------------------------------------------------ + lldb::ValueObjectSP + GetReturnValueObject (); + + //------------------------------------------------------------------ + /// Checks whether the given plan is in the completed plans for this + /// stop. + /// + /// @param[in] plan + /// Pointer to the plan you're checking. + /// + /// @return + /// Returns true if the input plan is in the completed plan stack, + /// false otherwise. + //------------------------------------------------------------------ + bool + IsThreadPlanDone (ThreadPlan *plan); + + //------------------------------------------------------------------ + /// Checks whether the given plan is in the discarded plans for this + /// stop. + /// + /// @param[in] plan + /// Pointer to the plan you're checking. + /// + /// @return + /// Returns true if the input plan is in the discarded plan stack, + /// false otherwise. + //------------------------------------------------------------------ + bool + WasThreadPlanDiscarded (ThreadPlan *plan); + + //------------------------------------------------------------------ + /// Queues a generic thread plan. + /// + /// @param[in] plan_sp + /// The plan to queue. + /// + /// @param[in] abort_other_plans + /// \b true if we discard the currently queued plans and replace them with this one. + /// Otherwise this plan will go on the end of the plan stack. + /// + /// @return + /// A pointer to the last completed plan. + //------------------------------------------------------------------ + void + QueueThreadPlan (lldb::ThreadPlanSP &plan_sp, bool abort_other_plans); + + + //------------------------------------------------------------------ + /// Discards the plans queued on the plan stack of the current thread. This is + /// arbitrated by the "Master" ThreadPlans, using the "OkayToDiscard" call. + // But if \a force is true, all thread plans are discarded. + //------------------------------------------------------------------ + void + DiscardThreadPlans (bool force); + + //------------------------------------------------------------------ + /// Discards the plans queued on the plan stack of the current thread up to and + /// including up_to_plan_sp. + // + // @param[in] up_to_plan_sp + // Discard all plans up to and including this one. + //------------------------------------------------------------------ + void + DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp); + + void + DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr); + + //------------------------------------------------------------------ + /// Prints the current plan stack. + /// + /// @param[in] s + /// The stream to which to dump the plan stack info. + /// + //------------------------------------------------------------------ + void + DumpThreadPlans (Stream *s) const; + + virtual bool + CheckpointThreadState (ThreadStateCheckpoint &saved_state); + + virtual bool + RestoreRegisterStateFromCheckpoint (ThreadStateCheckpoint &saved_state); + + virtual bool + RestoreThreadStateFromCheckpoint (ThreadStateCheckpoint &saved_state); + + void + EnableTracer (bool value, bool single_step); + + void + SetTracer (lldb::ThreadPlanTracerSP &tracer_sp); + + //------------------------------------------------------------------ + // Get the thread index ID. The index ID that is guaranteed to not + // be re-used by a process. They start at 1 and increase with each + // new thread. This allows easy command line access by a unique ID + // that is easier to type than the actual system thread ID. + //------------------------------------------------------------------ + uint32_t + GetIndexID () const; + + + //------------------------------------------------------------------ + // The API ID is often the same as the Thread::GetID(), but not in + // all cases. Thread::GetID() is the user visible thread ID that + // clients would want to see. The API thread ID is the thread ID + // that is used when sending data to/from the debugging protocol. + //------------------------------------------------------------------ + virtual lldb::user_id_t + GetProtocolID () const + { + return GetID(); + } + + //------------------------------------------------------------------ + // lldb::ExecutionContextScope pure virtual functions + //------------------------------------------------------------------ + virtual lldb::TargetSP + CalculateTarget (); + + virtual lldb::ProcessSP + CalculateProcess (); + + virtual lldb::ThreadSP + CalculateThread (); + + virtual lldb::StackFrameSP + CalculateStackFrame (); + + virtual void + CalculateExecutionContext (ExecutionContext &exe_ctx); + + lldb::StackFrameSP + GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr); + + size_t + GetStatus (Stream &strm, + uint32_t start_frame, + uint32_t num_frames, + uint32_t num_frames_with_source); + + size_t + GetStackFrameStatus (Stream& strm, + uint32_t first_frame, + uint32_t num_frames, + bool show_frame_info, + uint32_t num_frames_with_source); + + // We need a way to verify that even though we have a thread in a shared + // pointer that the object itself is still valid. Currently this won't be + // the case if DestroyThread() was called. DestroyThread is called when + // a thread has been removed from the Process' thread list. + bool + IsValid () const + { + return !m_destroy_called; + } + + // Sets and returns a valid stop info based on the process stop ID and the + // current thread plan. If the thread stop ID does not match the process' + // stop ID, the private stop reason is not set and an invalid StopInfoSP may + // be returned. + // + // NOTE: This function must be called before the current thread plan is + // moved to the completed plan stack (in Thread::ShouldStop()). + // + // NOTE: If subclasses override this function, ensure they do not overwrite + // the m_actual_stop_info if it is valid. The stop info may be a + // "checkpointed and restored" stop info, so if it is still around it is + // right even if you have not calculated this yourself, or if it disagrees + // with what you might have calculated. + virtual lldb::StopInfoSP + GetPrivateStopInfo (); + + //---------------------------------------------------------------------- + // Ask the thread subclass to set its stop info. + // + // Thread subclasses should call Thread::SetStopInfo(...) with the + // reason the thread stopped. + // + // @return + // True if Thread::SetStopInfo(...) was called, false otherwise. + //---------------------------------------------------------------------- + virtual bool + CalculateStopInfo () = 0; + + //---------------------------------------------------------------------- + // Gets the temporary resume state for a thread. + // + // This value gets set in each thread by complex debugger logic in + // Thread::ShouldResume() and an appropriate thread resume state will get + // set in each thread every time the process is resumed prior to calling + // Process::DoResume(). The lldb_private::Process subclass should adhere + // to the thread resume state request which will be one of: + // + // eStateRunning - thread will resume when process is resumed + // eStateStepping - thread should step 1 instruction and stop when process + // is resumed + // eStateSuspended - thread should not execute any instructions when + // process is resumed + //---------------------------------------------------------------------- + lldb::StateType + GetTemporaryResumeState() const + { + return m_temporary_resume_state; + } + + void + SetStopInfo (const lldb::StopInfoSP &stop_info_sp); + + void + SetShouldReportStop (Vote vote); + +protected: + + friend class ThreadPlan; + friend class ThreadList; + friend class ThreadEventData; + friend class StackFrameList; + friend class StackFrame; + friend class OperatingSystem; + + // This is necessary to make sure thread assets get destroyed while the thread is still in good shape + // to call virtual thread methods. This must be called by classes that derive from Thread in their destructor. + virtual void DestroyThread (); + + void + PushPlan (lldb::ThreadPlanSP &plan_sp); + + void + PopPlan (); + + void + DiscardPlan (); + + ThreadPlan *GetPreviousPlan (ThreadPlan *plan); + + typedef std::vector<lldb::ThreadPlanSP> plan_stack; + + virtual bool + SaveFrameZeroState (RegisterCheckpoint &checkpoint); + + virtual bool + RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint); + + // register_data_sp must be a DataSP passed to ReadAllRegisterValues. + bool + ResetFrameZeroRegisters (lldb::DataBufferSP register_data_sp); + + virtual lldb_private::Unwind * + GetUnwinder (); + + // Check to see whether the thread is still at the last breakpoint hit that stopped it. + virtual bool + IsStillAtLastBreakpointHit(); + + // Some threads are threads that are made up by OperatingSystem plugins that + // are threads that exist and are context switched out into memory. The + // OperatingSystem plug-in need a ways to know if a thread is "real" or made + // up. + virtual bool + IsOperatingSystemPluginThread () const + { + return false; + } + + + lldb::StackFrameListSP + GetStackFrameList (); + + struct ThreadState + { + uint32_t orig_stop_id; + lldb::StopInfoSP stop_info_sp; + RegisterCheckpoint register_backup; + }; + + //------------------------------------------------------------------ + // Classes that inherit from Process can see and modify these + //------------------------------------------------------------------ + lldb::ProcessWP m_process_wp; ///< The process that owns this thread. + lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread + uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that + // the thread's m_stop_info_sp is current and you don't have to fetch it again + const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread for easy UI/command line access. + lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this thread's current register state. + lldb::StateType m_state; ///< The state of our process. + mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state. + plan_stack m_plan_stack; ///< The stack of plans this thread is executing. + plan_stack m_completed_plan_stack; ///< Plans that have been completed by this stop. They get deleted when the thread resumes. + plan_stack m_discarded_plan_stack; ///< Plans that have been discarded by this stop. They get deleted when the thread resumes. + mutable Mutex m_frame_mutex; ///< Multithreaded protection for m_state. + lldb::StackFrameListSP m_curr_frames_sp; ///< The stack frames that get lazily populated after a thread stops. + lldb::StackFrameListSP m_prev_frames_sp; ///< The previous stack frames from the last time this thread stopped. + int m_resume_signal; ///< The signal that should be used when continuing this thread. + lldb::StateType m_resume_state; ///< This state is used to force a thread to be suspended from outside the ThreadPlan logic. + lldb::StateType m_temporary_resume_state; ///< This state records what the thread was told to do by the thread plan logic for the current resume. + /// It gets set in Thread::ShoudResume. + std::unique_ptr<lldb_private::Unwind> m_unwinder_ap; + bool m_destroy_called; // This is used internally to make sure derived Thread classes call DestroyThread. + LazyBool m_override_should_notify; +private: + //------------------------------------------------------------------ + // For Thread only + //------------------------------------------------------------------ + + DISALLOW_COPY_AND_ASSIGN (Thread); + +}; + +} // namespace lldb_private + +#endif // liblldb_Thread_h_ diff --git a/include/lldb/Target/ThreadList.h b/include/lldb/Target/ThreadList.h new file mode 100644 index 0000000..ddf49b0 --- /dev/null +++ b/include/lldb/Target/ThreadList.h @@ -0,0 +1,163 @@ +//===-- ThreadList.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_ThreadList_h_ +#define liblldb_ThreadList_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/UserID.h" + + +// FIXME: Currently this is a thread list with lots of functionality for use only by +// the process for which this is the thread list. If we ever want a container class +// to hand out that is just a random subset of threads, with iterator functionality, +// then we should make that part a base class, and make a ProcessThreadList for the +// process. +namespace lldb_private { + +class ThreadList +{ +friend class Process; + +public: + + ThreadList (Process *process); + + ThreadList (const ThreadList &rhs); + + ~ThreadList (); + + const ThreadList& + operator = (const ThreadList& rhs); + + uint32_t + GetSize(bool can_update = true); + + void + AddThread (const lldb::ThreadSP &thread_sp); + + // Return the selected thread if there is one. Otherwise, return the thread + // selected at index 0. + lldb::ThreadSP + GetSelectedThread (); + + bool + SetSelectedThreadByID (lldb::tid_t tid, bool notify = false); + + bool + SetSelectedThreadByIndexID (uint32_t index_id, bool notify = false); + + void + Clear(); + + void + Flush(); + + void + Destroy(); + + // Note that "idx" is not the same as the "thread_index". It is a zero + // based index to accessing the current threads, whereas "thread_index" + // is a unique index assigned + lldb::ThreadSP + GetThreadAtIndex (uint32_t idx, bool can_update = true); + + lldb::ThreadSP + FindThreadByID (lldb::tid_t tid, bool can_update = true); + + lldb::ThreadSP + FindThreadByProtocolID (lldb::tid_t tid, bool can_update = true); + + lldb::ThreadSP + RemoveThreadByID (lldb::tid_t tid, bool can_update = true); + + lldb::ThreadSP + RemoveThreadByProtocolID (lldb::tid_t tid, bool can_update = true); + + lldb::ThreadSP + FindThreadByIndexID (uint32_t index_id, bool can_update = true); + + lldb::ThreadSP + GetThreadSPForThreadPtr (Thread *thread_ptr); + + bool + ShouldStop (Event *event_ptr); + + Vote + ShouldReportStop (Event *event_ptr); + + Vote + ShouldReportRun (Event *event_ptr); + + void + RefreshStateAfterStop (); + + //------------------------------------------------------------------ + /// The thread list asks tells all the threads it is about to resume. + /// If a thread can "resume" without having to resume the target, it + /// will return false for WillResume, and then the process will not be + /// restarted. + /// + /// @return + /// \b true instructs the process to resume normally, + /// \b false means start & stopped events will be generated, but + /// the process will not actually run. The thread must then return + /// the correct StopInfo when asked. + /// + //------------------------------------------------------------------ + bool + WillResume (); + + void + DidResume (); + + void + DidStop (); + + void + DiscardThreadPlans(); + + uint32_t + GetStopID () const; + + void + SetStopID (uint32_t stop_id); + + Mutex & + GetMutex (); + + void + Update (ThreadList &rhs); + +protected: + + void + SetShouldReportStop (Vote vote); + + void + NotifySelectedThreadChanged (lldb::tid_t tid); + + typedef std::vector<lldb::ThreadSP> collection; + //------------------------------------------------------------------ + // Classes that inherit from Process can see and modify these + //------------------------------------------------------------------ + Process *m_process; ///< The process that manages this thread list. + uint32_t m_stop_id; ///< The process stop ID that this thread list is valid for. + collection m_threads; ///< The threads for this process. + lldb::tid_t m_selected_tid; ///< For targets that need the notion of a current thread. + +private: + ThreadList (); +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadList_h_ diff --git a/include/lldb/Target/ThreadPlan.h b/include/lldb/Target/ThreadPlan.h new file mode 100644 index 0000000..3c83fd1 --- /dev/null +++ b/include/lldb/Target/ThreadPlan.h @@ -0,0 +1,658 @@ +//===-- ThreadPlan.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_ThreadPlan_h_ +#define liblldb_ThreadPlan_h_ + +// C Includes +// C++ Includes +#include <string> +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/UserID.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanTracer.h" +#include "lldb/Target/StopInfo.h" + +namespace lldb_private { + +//------------------------------------------------------------------ +// ThreadPlan: +// This is the pure virtual base class for thread plans. +// +// The thread plans provide the "atoms" of behavior that +// all the logical process control, either directly from commands or through +// more complex composite plans will rely on. +// +// Plan Stack: +// +// The thread maintaining a thread plan stack, and you program the actions of a particular thread +// by pushing plans onto the plan stack. +// There is always a "Current" plan, which is the head of the plan stack, though in some cases +// a plan may defer to plans higher in the stack for some piece of information. +// +// The plan stack is never empty, there is always a Base Plan which persists through the life +// of the running process. +// +// +// Creating Plans: +// +// The thread plan is generally created and added to the plan stack through the QueueThreadPlanFor... API +// in lldb::Thread. Those API's will return the plan that performs the named operation in a manner +// appropriate for the current process. The plans in lldb/source/Target are generic +// implementations, but a Process plugin can override them. +// +// ValidatePlan is then called. If it returns false, the plan is unshipped. This is a little +// convenience which keeps us from having to error out of the constructor. +// +// Then the plan is added to the plan stack. When the plan is added to the plan stack its DidPush +// will get called. This is useful if a plan wants to push any additional plans as it is constructed, +// since you need to make sure you're already on the stack before you push additional plans. +// +// Completed Plans: +// +// When the target process stops the plans are queried, among other things, for whether their job is done. +// If it is they are moved from the plan stack to the Completed Plan stack in reverse order from their position +// on the plan stack (since multiple plans may be done at a given stop.) This is used primarily so that +// the lldb::Thread::StopInfo for the thread can be set properly. If one plan pushes another to achieve part of +// its job, but it doesn't want that sub-plan to be the one that sets the StopInfo, then call SetPrivate on the +// sub-plan when you create it, and the Thread will pass over that plan in reporting the reason for the stop. +// +// Discarded plans: +// +// Your plan may also get discarded, i.e. moved from the plan stack to the "discarded plan stack". This can +// happen, for instance, if the plan is calling a function and the function call crashes and you want +// to unwind the attempt to call. So don't assume that your plan will always successfully stop. Which leads to: +// +// Cleaning up after your plans: +// +// When the plan is moved from the plan stack its WillPop method is always called, no matter why. Once it is +// moved off the plan stack it is done, and won't get a chance to run again. So you should +// undo anything that affects target state in this method. But be sure to leave the plan able to correctly +// fill the StopInfo, however. +// N.B. Don't wait to do clean up target state till the destructor, since that will usually get called when +// the target resumes, and you want to leave the target state correct for new plans in the time between when +// your plan gets unshipped and the next resume. +// +// Over the lifetime of the plan, various methods of the ThreadPlan are then called in response to changes of state in +// the process we are debugging as follows: +// +// Resuming: +// +// When the target process is about to be restarted, the plan's WillResume method is called, +// giving the plan a chance to prepare for the run. If WillResume returns false, then the +// process is not restarted. Be sure to set an appropriate error value in the Process if +// you have to do this. Note, ThreadPlans actually implement DoWillResume, WillResume wraps that call. +// +// Next the "StopOthers" method of all the threads are polled, and if one thread's Current plan +// returns "true" then only that thread gets to run. If more than one returns "true" the threads that want to run solo +// get run one by one round robin fashion. Otherwise all are let to run. +// +// Note, the way StopOthers is implemented, the base class implementation just asks the previous plan. So if your plan +// has no opinion about whether it should run stopping others or not, just don't implement StopOthers, and the parent +// will be asked. +// +// Finally, for each thread that is running, it run state is set to the return of RunState from the +// thread's Current plan. +// +// Responding to a stop: +// +// When the target process stops, the plan is called in the following stages: +// +// First the thread asks the Current Plan if it can handle this stop by calling PlanExplainsStop. +// If the Current plan answers "true" then it is asked if the stop should percolate all the way to the +// user by calling the ShouldStop method. If the current plan doesn't explain the stop, then we query down +// the plan stack for a plan that does explain the stop. The plan that does explain the stop then needs to +// figure out what to do about the plans below it in the stack. If the stop is recoverable, then the plan that +// understands it can just do what it needs to set up to restart, and then continue. +// Otherwise, the plan that understood the stop should call DiscardPlanStack to clean up the stack below it. +// Note, plans actually implement DoPlanExplainsStop, the result is cached in PlanExplainsStop so the DoPlanExplainsStop +// itself will only get called once per stop. +// +// Master plans: +// +// In the normal case, when we decide to stop, we will collapse the plan stack up to the point of the plan that understood +// the stop reason. However, if a plan wishes to stay on the stack after an event it didn't directly handle +// it can designate itself a "Master" plan by responding true to IsMasterPlan, and then if it wants not to be +// discarded, it can return true to OkayToDiscard, and it and all its dependent plans will be preserved when +// we resume execution. +// +// The other effect of being a master plan is that when the Master plan is done , if it has set "OkayToDiscard" to false, +// then it will be popped & execution will stop and return to the user. Remember that if OkayToDiscard is false, the +// plan will be popped and control will be given to the next plan above it on the stack So setting OkayToDiscard to +// false means the user will regain control when the MasterPlan is completed. +// +// Between these two controls this allows things like: a MasterPlan/DontDiscard Step Over to hit a breakpoint, stop and +// return control to the user, but then when the user continues, the step out succeeds. +// Even more tricky, when the breakpoint is hit, the user can continue to step in/step over/etc, and finally when they +// continue, they will finish up the Step Over. +// +// FIXME: MasterPlan & OkayToDiscard aren't really orthogonal. MasterPlan designation means that this plan controls +// it's fate and the fate of plans below it. OkayToDiscard tells whether the MasterPlan wants to stay on the stack. I +// originally thought "MasterPlan-ness" would need to be a fixed characteristic of a ThreadPlan, in which case you needed +// the extra control. But that doesn't seem to be true. So we should be able to convert to only MasterPlan status to mean +// the current "MasterPlan/DontDiscard". Then no plans would be MasterPlans by default, and you would set the ones you +// wanted to be "user level" in this way. +// +// +// Actually Stopping: +// +// If a plan says responds "true" to ShouldStop, then it is asked if it's job is complete by calling +// MischiefManaged. If that returns true, the thread is popped from the plan stack and added to the +// Completed Plan Stack. Then the next plan in the stack is asked if it ShouldStop, and it returns "true", +// it is asked if it is done, and if yes popped, and so on till we reach a plan that is not done. +// +// Since you often know in the ShouldStop method whether your plan is complete, as a convenience you can call +// SetPlanComplete and the ThreadPlan implementation of MischiefManaged will return "true", without your having +// to redo the calculation when your sub-classes MischiefManaged is called. If you call SetPlanComplete, you can +// later use IsPlanComplete to determine whether the plan is complete. This is only a convenience for sub-classes, +// the logic in lldb::Thread will only call MischiefManaged. +// +// One slightly tricky point is you have to be careful using SetPlanComplete in PlanExplainsStop because you +// are not guaranteed that PlanExplainsStop for a plan will get called before ShouldStop gets called. If your sub-plan +// explained the stop and then popped itself, only your ShouldStop will get called. +// +// If ShouldStop for any thread returns "true", then the WillStop method of the Current plan of +// all threads will be called, the stop event is placed on the Process's public broadcaster, and +// control returns to the upper layers of the debugger. +// +// Reporting the stop: +// +// When the process stops, the thread is given a StopReason, in the form of a StopInfo object. If there is a completed +// plan corresponding to the stop, then the "actual" stop reason will be suppressed, and instead a StopInfoThreadPlan +// object will be cons'ed up from the highest completed plan in the stack. However, if the plan doesn't want to be +// the stop reason, then it can call SetPlanComplete and pass in "false" for the "success" parameter. In that case, +// the real stop reason will be used instead. One exapmle of this is the "StepRangeStepIn" thread plan. If it stops +// because of a crash or breakpoint hit, it wants to unship itself, because it isn't so useful to have step in keep going +// after a breakpoint hit. But it can't be the reason for the stop or no-one would see that they had hit a breakpoint. +// +// Cleaning up the plan stack: +// +// One of the complications of MasterPlans is that you may get past the limits of a plan without triggering it to clean +// itself up. For instance, if you are doing a MasterPlan StepOver, and hit a breakpoint in a called function, then +// step over enough times to step out of the initial StepOver range, each of the step overs will explain the stop & +// take themselves off the stack, but control would never be returned to the original StepOver. Eventually, the user +// will continue, and when that continue stops, the old stale StepOver plan that was left on the stack will get woken +// up and notice it is done. But that can leave junk on the stack for a while. To avoid that, the plans implement a +// "IsPlanStale" method, that can check whether it is relevant anymore. On stop, after the regular plan negotiation, +// the remaining plan stack is consulted and if any plan says it is stale, it and the plans below it are discarded from +// the stack. +// +// Automatically Resuming: +// +// If ShouldStop for all threads returns "false", then the target process will resume. This then cycles back to +// Resuming above. +// +// Reporting eStateStopped events when the target is restarted: +// +// If a plan decides to auto-continue the target by returning "false" from ShouldStop, then it will be asked +// whether the Stopped event should still be reported. For instance, if you hit a breakpoint that is a User set +// breakpoint, but the breakpoint callback said to continue the target process, you might still want to inform +// the upper layers of lldb that the stop had happened. +// The way this works is every thread gets to vote on whether to report the stop. If all votes are eVoteNoOpinion, +// then the thread list will decide what to do (at present it will pretty much always suppress these stopped events.) +// If there is an eVoteYes, then the event will be reported regardless of the other votes. If there is an eVoteNo +// and no eVoteYes's, then the event won't be reported. +// +// One other little detail here, sometimes a plan will push another plan onto the plan stack to do some part of +// the first plan's job, and it would be convenient to tell that plan how it should respond to ShouldReportStop. +// You can do that by setting the stop_vote in the child plan when you create it. +// +// Suppressing the initial eStateRunning event: +// +// The private process running thread will take care of ensuring that only one "eStateRunning" event will be +// delivered to the public Process broadcaster per public eStateStopped event. However there are some cases +// where the public state of this process is eStateStopped, but a thread plan needs to restart the target, but +// doesn't want the running event to be publically broadcast. The obvious example of this is running functions +// by hand as part of expression evaluation. To suppress the running event return eVoteNo from ShouldReportStop, +// to force a running event to be reported return eVoteYes, in general though you should return eVoteNoOpinion +// which will allow the ThreadList to figure out the right thing to do. +// The run_vote argument to the constructor works like stop_vote, and is a way for a plan to instruct a sub-plan +// on how to respond to ShouldReportStop. +// +//------------------------------------------------------------------ + +class ThreadPlan : + public UserID +{ +public: + typedef enum + { + eAllThreads, + eSomeThreads, + eThisThread + } ThreadScope; + + // We use these enums so that we can cast a base thread plan to it's real type without having to resort + // to dynamic casting. + typedef enum + { + eKindGeneric, + eKindNull, + eKindBase, + eKindCallFunction, + eKindStepInstruction, + eKindStepOut, + eKindStepOverBreakpoint, + eKindStepOverRange, + eKindStepInRange, + eKindRunToAddress, + eKindStepThrough, + eKindStepUntil, + eKindTestCondition + + } ThreadPlanKind; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ThreadPlan (ThreadPlanKind kind, + const char *name, + Thread &thread, + Vote stop_vote, + Vote run_vote); + + virtual + ~ThreadPlan(); + + //------------------------------------------------------------------ + /// Returns the name of this thread plan. + /// + /// @return + /// A const char * pointer to the thread plan's name. + //------------------------------------------------------------------ + const char * + GetName () const + { + return m_name.c_str(); + } + + //------------------------------------------------------------------ + /// Returns the Thread that is using this thread plan. + /// + /// @return + /// A pointer to the thread plan's owning thread. + //------------------------------------------------------------------ + Thread & + GetThread() + { + return m_thread; + } + + const Thread & + GetThread() const + { + return m_thread; + } + + Target & + GetTarget() + { + return m_thread.GetProcess()->GetTarget(); + } + + const Target & + GetTarget() const + { + return m_thread.GetProcess()->GetTarget(); + } + + //------------------------------------------------------------------ + /// Print a description of this thread to the stream \a s. + /// \a thread. + /// + /// @param[in] s + /// The stream to which to print the description. + /// + /// @param[in] level + /// The level of description desired. Note that eDescriptionLevelBrief + /// will be used in the stop message printed when the plan is complete. + //------------------------------------------------------------------ + virtual void + GetDescription (Stream *s, + lldb::DescriptionLevel level) = 0; + + //------------------------------------------------------------------ + /// Returns whether this plan could be successfully created. + /// + /// @param[in] error + /// A stream to which to print some reason why the plan could not be created. + /// Can be NULL. + /// + /// @return + /// \b true if the plan should be queued, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + ValidatePlan (Stream *error) = 0; + + bool + TracerExplainsStop () + { + if (!m_tracer_sp) + return false; + else + return m_tracer_sp->TracerExplainsStop(); + } + + + lldb::StateType + RunState (); + + bool + PlanExplainsStop (Event *event_ptr); + + virtual bool + ShouldStop (Event *event_ptr) = 0; + + virtual bool + ShouldAutoContinue (Event *event_ptr) + { + return false; + } + + // Whether a "stop class" event should be reported to the "outside world". In general + // if a thread plan is active, events should not be reported. + + virtual Vote + ShouldReportStop (Event *event_ptr); + + virtual Vote + ShouldReportRun (Event *event_ptr); + + virtual void + SetStopOthers (bool new_value); + + virtual bool + StopOthers (); + + // This is the wrapper for DoWillResume that does generic ThreadPlan logic, then + // calls DoWillResume. + bool + WillResume (lldb::StateType resume_state, bool current_plan); + + virtual bool + WillStop () = 0; + + bool + IsMasterPlan() + { + return m_is_master_plan; + } + + bool + SetIsMasterPlan (bool value) + { + bool old_value = m_is_master_plan; + m_is_master_plan = value; + return old_value; + } + + virtual bool + OkayToDiscard(); + + void + SetOkayToDiscard (bool value) + { + m_okay_to_discard = value; + } + + // The base class MischiefManaged does some cleanup - so you have to call it + // in your MischiefManaged derived class. + virtual bool + MischiefManaged (); + + virtual void + ThreadDestroyed () + { + // Any cleanup that a plan might want to do in case the thread goes away + // in the middle of the plan being queued on a thread can be done here. + } + + bool + GetPrivate () + { + return m_plan_private; + } + + void + SetPrivate (bool input) + { + m_plan_private = input; + } + + virtual void + DidPush(); + + virtual void + WillPop(); + + // This pushes a plan onto the plan stack of the current plan's thread. + void + PushPlan (lldb::ThreadPlanSP &thread_plan_sp) + { + m_thread.PushPlan (thread_plan_sp); + } + + ThreadPlanKind GetKind() const + { + return m_kind; + } + + bool + IsPlanComplete(); + + void + SetPlanComplete (bool success = true); + + virtual bool + IsPlanStale () + { + return false; + } + + bool + PlanSucceeded () + { + return m_plan_succeeded; + } + + virtual bool + IsBasePlan() + { + return false; + } + + lldb::ThreadPlanTracerSP & + GetThreadPlanTracer() + { + return m_tracer_sp; + } + + void + SetThreadPlanTracer (lldb::ThreadPlanTracerSP new_tracer_sp) + { + m_tracer_sp = new_tracer_sp; + } + + void + DoTraceLog () + { + if (m_tracer_sp && m_tracer_sp->TracingEnabled()) + m_tracer_sp->Log(); + } + + // Some thread plans hide away the actual stop info which caused any particular stop. For + // instance the ThreadPlanCallFunction restores the original stop reason so that stopping and + // calling a few functions won't lose the history of the run. + // This call can be implemented to get you back to the real stop info. + virtual lldb::StopInfoSP + GetRealStopInfo () + { + return m_thread.GetStopInfo (); + } + + virtual lldb::ValueObjectSP + GetReturnValueObject () + { + return lldb::ValueObjectSP(); + } + + // If a thread plan stores the state before it was run, then you might + // want to restore the state when it is done. This will do that job. + // This is mostly useful for artificial plans like CallFunction plans. + + virtual bool + RestoreThreadState() + { + // Nothing to do in general. + return true; + } + + virtual bool + IsVirtualStep() + { + return false; + } + +protected: + //------------------------------------------------------------------ + // Classes that inherit from ThreadPlan can see and modify these + //------------------------------------------------------------------ + + virtual bool + DoWillResume (lldb::StateType resume_state, bool current_plan) { return true; }; + + virtual bool + DoPlanExplainsStop (Event *event_ptr) = 0; + + // This gets the previous plan to the current plan (for forwarding requests). + // This is mostly a formal requirement, it allows us to make the Thread's + // GetPreviousPlan protected, but only friend ThreadPlan to thread. + + ThreadPlan * + GetPreviousPlan () + { + return m_thread.GetPreviousPlan (this); + } + + // This forwards the private Thread::GetPrivateStopInfo which is generally what + // ThreadPlan's need to know. + + lldb::StopInfoSP + GetPrivateStopInfo() + { + return m_thread.GetPrivateStopInfo (); + } + + void + SetStopInfo (lldb::StopInfoSP stop_reason_sp) + { + m_thread.SetStopInfo (stop_reason_sp); + } + + void + CachePlanExplainsStop (bool does_explain) + { + m_cached_plan_explains_stop = does_explain ? eLazyBoolYes : eLazyBoolNo; + } + + LazyBool + GetCachedPlanExplainsStop () const + { + return m_cached_plan_explains_stop; + } + + virtual lldb::StateType + GetPlanRunState () = 0; + + Thread &m_thread; + Vote m_stop_vote; + Vote m_run_vote; + +private: + //------------------------------------------------------------------ + // For ThreadPlan only + //------------------------------------------------------------------ + static lldb::user_id_t GetNextID (); + + ThreadPlanKind m_kind; + std::string m_name; + Mutex m_plan_complete_mutex; + LazyBool m_cached_plan_explains_stop; + bool m_plan_complete; + bool m_plan_private; + bool m_okay_to_discard; + bool m_is_master_plan; + bool m_plan_succeeded; + + lldb::ThreadPlanTracerSP m_tracer_sp; + +private: + DISALLOW_COPY_AND_ASSIGN(ThreadPlan); +}; + +//---------------------------------------------------------------------- +// ThreadPlanNull: +// Threads are assumed to always have at least one plan on the plan stack. +// This is put on the plan stack when a thread is destroyed so that if you +// accidentally access a thread after it is destroyed you won't crash. +// But asking questions of the ThreadPlanNull is definitely an error. +//---------------------------------------------------------------------- + +class ThreadPlanNull : public ThreadPlan +{ +public: + ThreadPlanNull (Thread &thread); + virtual ~ThreadPlanNull (); + + virtual void + GetDescription (Stream *s, + lldb::DescriptionLevel level); + + virtual bool + ValidatePlan (Stream *error); + + virtual bool + ShouldStop (Event *event_ptr); + + virtual bool + MischiefManaged (); + + virtual bool + WillStop (); + + virtual bool + IsBasePlan() + { + return true; + } + + virtual bool + OkayToDiscard () + { + return false; + } + +protected: + virtual bool + DoPlanExplainsStop (Event *event_ptr); + + virtual lldb::StateType + GetPlanRunState (); + +}; + + +} // namespace lldb_private + +#endif // liblldb_ThreadPlan_h_ diff --git a/include/lldb/Target/ThreadPlanBase.h b/include/lldb/Target/ThreadPlanBase.h new file mode 100644 index 0000000..69959e1 --- /dev/null +++ b/include/lldb/Target/ThreadPlanBase.h @@ -0,0 +1,71 @@ +//===-- ThreadPlanBase.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_ThreadPlanFundamental_h_ +#define liblldb_ThreadPlanFundamental_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + + +//------------------------------------------------------------------ +// Base thread plans: +// This is the generic version of the bottom most plan on the plan stack. It should +// be able to handle generic breakpoint hitting, and signals and exceptions. +//------------------------------------------------------------------ + +class ThreadPlanBase : public ThreadPlan +{ +friend class Process; // RunThreadPlan manages "stopper" base plans. +public: + virtual ~ThreadPlanBase (); + + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); + virtual bool ValidatePlan (Stream *error); + virtual bool ShouldStop (Event *event_ptr); + virtual Vote ShouldReportStop (Event *event_ptr); + virtual bool StopOthers (); + virtual lldb::StateType GetPlanRunState (); + virtual bool WillStop (); + virtual bool MischiefManaged (); + + virtual bool OkayToDiscard() + { + return false; + } + + virtual bool + IsBasePlan() + { + return true; + } + +protected: + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + virtual bool DoPlanExplainsStop (Event *event_ptr); + ThreadPlanBase (Thread &thread); + +private: + friend lldb::ThreadPlanSP + Thread::QueueFundamentalPlan(bool abort_other_plans); + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanBase); +}; + + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanFundamental_h_ diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h new file mode 100644 index 0000000..d747706 --- /dev/null +++ b/include/lldb/Target/ThreadPlanCallFunction.h @@ -0,0 +1,193 @@ +//===-- ThreadPlanCallFunction.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_ThreadPlanCallFunction_h_ +#define liblldb_ThreadPlanCallFunction_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + +class ThreadPlanCallFunction : public ThreadPlan +{ + // Create a thread plan to call a function at the address passed in the "function" + // argument. If you plan to call GetReturnValueObject, then pass in the + // return type, otherwise just pass in an invalid ClangASTType. +public: + ThreadPlanCallFunction (Thread &thread, + const Address &function, + const ClangASTType &return_type, + lldb::addr_t arg, + bool stop_other_threads, + bool unwind_on_error = true, + bool ignore_breakpoints = false, + lldb::addr_t *this_arg = 0, + lldb::addr_t *cmd_arg = 0); + + ThreadPlanCallFunction (Thread &thread, + const Address &function, + const ClangASTType &return_type, + bool stop_other_threads, + bool unwind_on_error, + bool ignore_breakpoints, + lldb::addr_t *arg1_ptr = NULL, + lldb::addr_t *arg2_ptr = NULL, + lldb::addr_t *arg3_ptr = NULL, + lldb::addr_t *arg4_ptr = NULL, + lldb::addr_t *arg5_ptr = NULL, + lldb::addr_t *arg6_ptr = NULL); + + virtual + ~ThreadPlanCallFunction (); + + virtual void + GetDescription (Stream *s, lldb::DescriptionLevel level); + + virtual bool + ValidatePlan (Stream *error); + + virtual bool + ShouldStop (Event *event_ptr); + + virtual Vote + ShouldReportStop(Event *event_ptr); + + virtual bool + StopOthers (); + + virtual void + SetStopOthers (bool new_value); + + virtual lldb::StateType + GetPlanRunState (); + + virtual void + DidPush (); + + virtual bool + WillStop (); + + virtual bool + MischiefManaged (); + + // To get the return value from a function call you must create a + // lldb::ValueSP that contains a valid clang type in its context and call + // RequestReturnValue. The ValueSP will be stored and when the function is + // done executing, the object will check if there is a requested return + // value. If there is, the return value will be retrieved using the + // ABI::GetReturnValue() for the ABI in the process. Then after the thread + // plan is complete, you can call "GetReturnValue()" to retrieve the value + // that was extracted. + + virtual lldb::ValueObjectSP + GetReturnValueObject () + { + return m_return_valobj_sp; + } + + // Return the stack pointer that the function received + // on entry. Any stack address below this should be + // considered invalid after the function has been + // cleaned up. + lldb::addr_t + GetFunctionStackPointer() + { + return m_function_sp; + } + + // Classes that derive from ClangFunction, and implement + // their own WillPop methods should call this so that the + // thread state gets restored if the plan gets discarded. + virtual void + WillPop (); + + // If the thread plan stops mid-course, this will be the stop reason that interrupted us. + // Once DoTakedown is called, this will be the real stop reason at the end of the function call. + // If it hasn't been set for one or the other of these reasons, we'll return the PrivateStopReason. + // This is needed because we want the CallFunction thread plans not to show up as the stop reason. + // But if something bad goes wrong, it is nice to be able to tell the user what really happened. + + virtual lldb::StopInfoSP + GetRealStopInfo() + { + if (m_real_stop_info_sp) + return m_real_stop_info_sp; + else + return GetPrivateStopInfo (); + } + + lldb::addr_t + GetStopAddress () + { + return m_stop_address; + } + + virtual bool + RestoreThreadState(); + +protected: + void ReportRegisterState (const char *message); + + virtual bool + DoPlanExplainsStop (Event *event_ptr); + +private: + + bool + ConstructorSetup (Thread &thread, + ABI *& abi, + lldb::addr_t &start_load_addr, + lldb::addr_t &function_load_addr); + + void + DoTakedown (bool success); + + void + SetBreakpoints (); + + void + ClearBreakpoints (); + + bool + BreakpointsExplainStop (); + + bool m_valid; + bool m_stop_other_threads; + Address m_function_addr; + Address m_start_addr; + lldb::addr_t m_function_sp; + Thread::RegisterCheckpoint m_register_backup; + lldb::ThreadPlanSP m_subplan_sp; + LanguageRuntime *m_cxx_language_runtime; + LanguageRuntime *m_objc_language_runtime; + Thread::ThreadStateCheckpoint m_stored_thread_state; + lldb::StopInfoSP m_real_stop_info_sp; // In general we want to hide call function + // thread plans, but for reporting purposes, + // it's nice to know the real stop reason. + // This gets set in DoTakedown. + StreamString m_constructor_errors; + ClangASTType m_return_type; + lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer, use the ABI to extract values when complete + bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that. + lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown; + bool m_unwind_on_error; + bool m_ignore_breakpoints; + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction); +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanCallFunction_h_ diff --git a/include/lldb/Target/ThreadPlanCallUserExpression.h b/include/lldb/Target/ThreadPlanCallUserExpression.h new file mode 100644 index 0000000..7a7ec33 --- /dev/null +++ b/include/lldb/Target/ThreadPlanCallUserExpression.h @@ -0,0 +1,65 @@ +//===-- ThreadPlanCallUserExpression.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_ThreadPlanCallUserExpression_h_ +#define liblldb_ThreadPlanCallUserExpression_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +namespace lldb_private { + +class ThreadPlanCallUserExpression : public ThreadPlanCallFunction +{ +public: + ThreadPlanCallUserExpression (Thread &thread, + Address &function, + lldb::addr_t arg, + bool stop_other_threads, + bool unwind_on_error, + bool ignore_breakpoints, + lldb::addr_t *this_arg, + lldb::addr_t *cmd_arg, + ClangUserExpression::ClangUserExpressionSP &user_expression_sp); + + virtual + ~ThreadPlanCallUserExpression (); + + virtual void + GetDescription (Stream *s, lldb::DescriptionLevel level); + + virtual void + WillPop () + { + ThreadPlanCallFunction::WillPop(); + if (m_user_expression_sp) + m_user_expression_sp.reset(); + } + + virtual lldb::StopInfoSP + GetRealStopInfo(); + +protected: +private: + ClangUserExpression::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the + // User expression the initiated this ThreadPlan + // lives as long as the thread plan does. + DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallUserExpression); +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanCallUserExpression_h_ diff --git a/include/lldb/Target/ThreadPlanRunToAddress.h b/include/lldb/Target/ThreadPlanRunToAddress.h new file mode 100644 index 0000000..d948206 --- /dev/null +++ b/include/lldb/Target/ThreadPlanRunToAddress.h @@ -0,0 +1,85 @@ +//===-- ThreadPlanRunToAddress.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_ThreadPlanRunToAddress_h_ +#define liblldb_ThreadPlanRunToAddress_h_ + +// C Includes +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + +class ThreadPlanRunToAddress : public ThreadPlan +{ +public: + ThreadPlanRunToAddress (Thread &thread, + Address &address, + bool stop_others); + + ThreadPlanRunToAddress (Thread &thread, + lldb::addr_t address, + bool stop_others); + + ThreadPlanRunToAddress (Thread &thread, + const std::vector<lldb::addr_t> &addresses, + bool stop_others); + + + virtual + ~ThreadPlanRunToAddress (); + + virtual void + GetDescription (Stream *s, lldb::DescriptionLevel level); + + virtual bool + ValidatePlan (Stream *error); + + virtual bool + ShouldStop (Event *event_ptr); + + virtual bool + StopOthers (); + + virtual void + SetStopOthers (bool new_value); + + virtual lldb::StateType + GetPlanRunState (); + + virtual bool + WillStop (); + + virtual bool + MischiefManaged (); + +protected: + virtual bool + DoPlanExplainsStop (Event *event_ptr); + + void SetInitialBreakpoints(); + bool AtOurAddress(); +private: + bool m_stop_others; + std::vector<lldb::addr_t> m_addresses; // This is the address we are going to run to. + // TODO: Would it be useful to have multiple addresses? + std::vector<lldb::break_id_t> m_break_ids; // This is the breakpoint we are using to stop us at m_address. + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanRunToAddress); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanRunToAddress_h_ diff --git a/include/lldb/Target/ThreadPlanShouldStopHere.h b/include/lldb/Target/ThreadPlanShouldStopHere.h new file mode 100644 index 0000000..62068b7 --- /dev/null +++ b/include/lldb/Target/ThreadPlanShouldStopHere.h @@ -0,0 +1,94 @@ +//===-- ThreadPlanShouldStopHere.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_ThreadPlanShouldStopHere_h_ +#define liblldb_ThreadPlanShouldStopHere_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + +// This is an interface that ThreadPlans can adopt to allow flexible modifications of the behavior +// when a thread plan comes to a place where it would ordinarily stop. If such modification makes +// sense for your plan, inherit from this class, and when you would be about to stop (in your ShouldStop +// method), call InvokeShouldStopHereCallback, and if that returns a non-NULL plan, execute that +// plan instead of stopping. +// +// The classic example of the use of this is ThreadPlanStepInRange not stopping in frames that have +// no debug information. +// +// This class also defines a set of flags to control general aspects of this "ShouldStop" behavior. +// A class implementing this protocol needs to define a default set of flags, and can provide access to +// changing that default flag set if it wishes. + +class ThreadPlanShouldStopHere +{ +public: + enum + { + eNone = 0, + eAvoidInlines = (1 << 0), + eAvoidNoDebug = (1 << 1) + }; + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ThreadPlanShouldStopHere (ThreadPlan *owner, + ThreadPlanShouldStopHereCallback callback = NULL, + void *baton = NULL); + virtual + ~ThreadPlanShouldStopHere(); + + void + SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton); + + lldb::ThreadPlanSP + InvokeShouldStopHereCallback (); + + lldb_private::Flags & + GetFlags () + { + return m_flags; + } + + const lldb_private::Flags & + GetFlags () const + { + return m_flags; + } + +protected: + // Implement this, and call it in the plan's constructor to set the default flags. + virtual void SetFlagsToDefault () = 0; + + //------------------------------------------------------------------ + // Classes that inherit from ThreadPlanShouldStopHere can see and modify these + //------------------------------------------------------------------ + ThreadPlanShouldStopHereCallback m_callback; + void * m_baton; + ThreadPlan *m_owner; + lldb_private::Flags m_flags; + +private: + //------------------------------------------------------------------ + // For ThreadPlanShouldStopHere only + //------------------------------------------------------------------ + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanShouldStopHere); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanShouldStopHere_h_ diff --git a/include/lldb/Target/ThreadPlanStepInRange.h b/include/lldb/Target/ThreadPlanStepInRange.h new file mode 100644 index 0000000..dbc8446 --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepInRange.h @@ -0,0 +1,110 @@ +//===-- ThreadPlanStepInRange.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_ThreadPlanStepInRange_h_ +#define liblldb_ThreadPlanStepInRange_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/AddressRange.h" +#include "lldb/Target/StackID.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanStepRange.h" +#include "lldb/Target/ThreadPlanShouldStopHere.h" + +namespace lldb_private { + +class ThreadPlanStepInRange : + public ThreadPlanStepRange, + public ThreadPlanShouldStopHere +{ +public: + ThreadPlanStepInRange (Thread &thread, + const AddressRange &range, + const SymbolContext &addr_context, + lldb::RunMode stop_others); + + ThreadPlanStepInRange (Thread &thread, + const AddressRange &range, + const SymbolContext &addr_context, + const char *step_into_function_name, + lldb::RunMode stop_others); + + virtual + ~ThreadPlanStepInRange (); + + virtual void + GetDescription (Stream *s, lldb::DescriptionLevel level); + + virtual bool + ShouldStop (Event *event_ptr); + + void SetAvoidRegexp(const char *name); + + void SetStepInTarget (const char *target) + { + m_step_into_target.SetCString(target); + } + + static lldb::ThreadPlanSP + DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton); + + static void + SetDefaultFlagValue (uint32_t new_value); + + bool + IsVirtualStep(); + +protected: + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + + virtual bool + DoPlanExplainsStop (Event *event_ptr); + + virtual void + SetFlagsToDefault (); + + bool + FrameMatchesAvoidRegexp (); + +private: + + friend lldb::ThreadPlanSP + Thread::QueueThreadPlanForStepOverRange (bool abort_other_plans, + const AddressRange &range, + const SymbolContext &addr_context, + lldb::RunMode stop_others); + friend lldb::ThreadPlanSP + Thread::QueueThreadPlanForStepInRange (bool abort_other_plans, + const AddressRange &range, + const SymbolContext &addr_context, + const char *step_in_target, + lldb::RunMode stop_others, + bool avoid_code_without_debug_info); + + + // Need an appropriate marker for the current stack so we can tell step out + // from step in. + + static uint32_t s_default_flag_values; + lldb::ThreadPlanSP m_sub_plan_sp; // Keep track of the last plan we were running. If it fails, we should stop. + std::unique_ptr<RegularExpression> m_avoid_regexp_ap; + bool m_step_past_prologue; // FIXME: For now hard-coded to true, we could put a switch in for this if there's + // demand for that. + bool m_virtual_step; // true if we've just done a "virtual step", i.e. just moved the inline stack depth. + ConstString m_step_into_target; + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInRange); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepInRange_h_ diff --git a/include/lldb/Target/ThreadPlanStepInstruction.h b/include/lldb/Target/ThreadPlanStepInstruction.h new file mode 100644 index 0000000..eb4a64b --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepInstruction.h @@ -0,0 +1,64 @@ +//===-- ThreadPlanStepInstruction.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_ThreadPlanStepInstruction_h_ +#define liblldb_ThreadPlanStepInstruction_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + +class ThreadPlanStepInstruction : public ThreadPlan +{ +public: + virtual ~ThreadPlanStepInstruction (); + + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); + virtual bool ValidatePlan (Stream *error); + virtual bool ShouldStop (Event *event_ptr); + virtual bool StopOthers (); + virtual lldb::StateType GetPlanRunState (); + virtual bool WillStop (); + virtual bool MischiefManaged (); + +protected: + virtual bool DoPlanExplainsStop (Event *event_ptr); + + ThreadPlanStepInstruction (Thread &thread, + bool step_over, + bool stop_others, + Vote stop_vote, + Vote run_vote); + +private: + friend lldb::ThreadPlanSP + Thread::QueueThreadPlanForStepSingleInstruction (bool step_over, bool abort_other_plans, bool stop_other_threads); + + lldb::addr_t m_instruction_addr; + bool m_stop_other_threads; + bool m_step_over; + // These two are used only for the step over case. + bool m_start_has_symbol; + StackID m_stack_id; + StackID m_parent_frame_id; + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepInstruction); + +}; + + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepInstruction_h_ diff --git a/include/lldb/Target/ThreadPlanStepOut.h b/include/lldb/Target/ThreadPlanStepOut.h new file mode 100644 index 0000000..2737978 --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepOut.h @@ -0,0 +1,90 @@ +//===-- ThreadPlanStepOut.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_ThreadPlanStepOut_h_ +#define liblldb_ThreadPlanStepOut_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + +class ThreadPlanStepOut : public ThreadPlan +{ +public: + ThreadPlanStepOut (Thread &thread, + SymbolContext *addr_context, + bool first_insn, + bool stop_others, + Vote stop_vote, + Vote run_vote, + uint32_t frame_idx); + + virtual ~ThreadPlanStepOut (); + + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); + virtual bool ValidatePlan (Stream *error); + virtual bool ShouldStop (Event *event_ptr); + virtual bool StopOthers (); + virtual lldb::StateType GetPlanRunState (); + virtual bool WillStop (); + virtual bool MischiefManaged (); + virtual void DidPush(); + virtual bool IsPlanStale(); + + virtual lldb::ValueObjectSP GetReturnValueObject() + { + return m_return_valobj_sp; + } + +protected: + virtual bool DoPlanExplainsStop (Event *event_ptr); + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + bool QueueInlinedStepPlan (bool queue_now); + +private: + SymbolContext *m_step_from_context; + lldb::addr_t m_step_from_insn; + StackID m_step_out_to_id; + StackID m_immediate_step_from_id; + lldb::break_id_t m_return_bp_id; + lldb::addr_t m_return_addr; + bool m_first_insn; + bool m_stop_others; + lldb::ThreadPlanSP m_step_through_inline_plan_sp; + lldb::ThreadPlanSP m_step_out_plan_sp; + Function *m_immediate_step_from_function; + lldb::ValueObjectSP m_return_valobj_sp; + + friend lldb::ThreadPlanSP + Thread::QueueThreadPlanForStepOut (bool abort_other_plans, + SymbolContext *addr_context, + bool first_insn, + bool stop_others, + Vote stop_vote, + Vote run_vote, + uint32_t frame_idx); + + // Need an appropriate marker for the current stack so we can tell step out + // from step in. + + void + CalculateReturnValue(); + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOut); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepOut_h_ diff --git a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h new file mode 100644 index 0000000..41cac5c --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h @@ -0,0 +1,57 @@ +//===-- ThreadPlanStepOverBreakpoint.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_ThreadPlanStepOverBreakpoint_h_ +#define liblldb_ThreadPlanStepOverBreakpoint_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + +class ThreadPlanStepOverBreakpoint : public ThreadPlan +{ +public: + virtual ~ThreadPlanStepOverBreakpoint (); + + ThreadPlanStepOverBreakpoint (Thread &thread); + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); + virtual bool ValidatePlan (Stream *error); + virtual bool ShouldStop (Event *event_ptr); + virtual bool StopOthers (); + virtual lldb::StateType GetPlanRunState (); + virtual bool WillStop (); + virtual bool MischiefManaged (); + virtual void ThreadDestroyed (); + void SetAutoContinue (bool do_it); + virtual bool ShouldAutoContinue(Event *event_ptr); + +protected: + virtual bool DoPlanExplainsStop (Event *event_ptr); + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + + void ReenableBreakpointSite (); +private: + + lldb::addr_t m_breakpoint_addr; + lldb::user_id_t m_breakpoint_site_id; + bool m_auto_continue; + bool m_reenabled_breakpoint_site; + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverBreakpoint); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepOverBreakpoint_h_ diff --git a/include/lldb/Target/ThreadPlanStepOverRange.h b/include/lldb/Target/ThreadPlanStepOverRange.h new file mode 100644 index 0000000..de9e668 --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepOverRange.h @@ -0,0 +1,52 @@ +//===-- ThreadPlanStepOverRange.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_ThreadPlanStepOverRange_h_ +#define liblldb_ThreadPlanStepOverRange_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/AddressRange.h" +#include "lldb/Target/StackID.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanStepRange.h" + +namespace lldb_private { + +class ThreadPlanStepOverRange : public ThreadPlanStepRange +{ +public: + + ThreadPlanStepOverRange (Thread &thread, + const AddressRange &range, + const SymbolContext &addr_context, + lldb::RunMode stop_others); + + virtual ~ThreadPlanStepOverRange (); + + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); + virtual bool ShouldStop (Event *event_ptr); + +protected: + virtual bool DoPlanExplainsStop (Event *event_ptr); + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + +private: + + bool m_first_resume; + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepOverRange_h_ diff --git a/include/lldb/Target/ThreadPlanStepRange.h b/include/lldb/Target/ThreadPlanStepRange.h new file mode 100644 index 0000000..486fd65 --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepRange.h @@ -0,0 +1,94 @@ +//===-- ThreadPlanStepRange.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_ThreadPlanStepRange_h_ +#define liblldb_ThreadPlanStepRange_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/AddressRange.h" +#include "lldb/Target/StackID.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanShouldStopHere.h" + +namespace lldb_private { + +class ThreadPlanStepRange : public ThreadPlan +{ +public: + ThreadPlanStepRange (ThreadPlanKind kind, + const char *name, + Thread &thread, + const AddressRange &range, + const SymbolContext &addr_context, + lldb::RunMode stop_others); + + virtual ~ThreadPlanStepRange (); + + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level) = 0; + virtual bool ValidatePlan (Stream *error); + virtual bool ShouldStop (Event *event_ptr) = 0; + virtual Vote ShouldReportStop (Event *event_ptr); + virtual bool StopOthers (); + virtual lldb::StateType GetPlanRunState (); + virtual bool WillStop (); + virtual bool MischiefManaged (); + virtual void DidPush (); + virtual bool IsPlanStale (); + + + void AddRange(const AddressRange &new_range); + +protected: + + bool InRange(); + lldb::FrameComparison CompareCurrentFrameToStartFrame(); + bool InSymbol(); + void DumpRanges (Stream *s); + + Disassembler * + GetDisassembler (); + + InstructionList * + GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset); + + // Pushes a plan to proceed through the next section of instructions in the range - usually just a RunToAddress + // plan to run to the next branch. Returns true if it pushed such a plan. If there was no available 'quick run' + // plan, then just single step. + bool + SetNextBranchBreakpoint (); + + void + ClearNextBranchBreakpoint(); + + bool + NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp); + + SymbolContext m_addr_context; + std::vector<AddressRange> m_address_ranges; + lldb::RunMode m_stop_others; + StackID m_stack_id; // Use the stack ID so we can tell step out from step in. + bool m_no_more_plans; // Need this one so we can tell if we stepped into a call, + // but can't continue, in which case we are done. + bool m_first_run_event; // We want to broadcast only one running event, our first. + lldb::BreakpointSP m_next_branch_bp_sp; + bool m_use_fast_step; + +private: + std::vector<lldb::DisassemblerSP> m_instruction_ranges; + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepRange); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepRange_h_ diff --git a/include/lldb/Target/ThreadPlanStepThrough.h b/include/lldb/Target/ThreadPlanStepThrough.h new file mode 100644 index 0000000..1697966 --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepThrough.h @@ -0,0 +1,71 @@ +//===-- ThreadPlanStepThrough.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_ThreadPlanStepThrough_h_ +#define liblldb_ThreadPlanStepThrough_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + +class ThreadPlanStepThrough : public ThreadPlan +{ +public: + virtual ~ThreadPlanStepThrough (); + + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); + virtual bool ValidatePlan (Stream *error); + virtual bool ShouldStop (Event *event_ptr); + virtual bool StopOthers (); + virtual lldb::StateType GetPlanRunState (); + virtual bool WillStop (); + virtual bool MischiefManaged (); + virtual void DidPush(); + +protected: + virtual bool DoPlanExplainsStop (Event *event_ptr); + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + + ThreadPlanStepThrough (Thread &thread, + StackID &return_stack_id, + bool stop_others); + + void + LookForPlanToStepThroughFromCurrentPC (); + + bool + HitOurBackstopBreakpoint(); + +private: + friend lldb::ThreadPlanSP + Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id, + bool abort_other_plans, + bool stop_others); + + void ClearBackstopBreakpoint(); + + lldb::ThreadPlanSP m_sub_plan_sp; + lldb::addr_t m_start_address; + lldb::break_id_t m_backstop_bkpt_id; + lldb::addr_t m_backstop_addr; + StackID m_return_stack_id; + bool m_stop_others; + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepThrough); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepThrough_h_ diff --git a/include/lldb/Target/ThreadPlanStepUntil.h b/include/lldb/Target/ThreadPlanStepUntil.h new file mode 100644 index 0000000..5aa3876 --- /dev/null +++ b/include/lldb/Target/ThreadPlanStepUntil.h @@ -0,0 +1,80 @@ +//===-- ThreadPlanStepUntil.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_ThreadPlanStepUntil_h_ +#define liblldb_ThreadPlanStepUntil_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" + +namespace lldb_private { + + +class ThreadPlanStepUntil : public ThreadPlan +{ +public: + virtual ~ThreadPlanStepUntil (); + + virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); + virtual bool ValidatePlan (Stream *error); + virtual bool ShouldStop (Event *event_ptr); + virtual bool StopOthers (); + virtual lldb::StateType GetPlanRunState (); + virtual bool WillStop (); + virtual bool MischiefManaged (); + +protected: + virtual bool DoWillResume (lldb::StateType resume_state, bool current_plan); + virtual bool DoPlanExplainsStop (Event *event_ptr); + + ThreadPlanStepUntil (Thread &thread, + lldb::addr_t *address_list, + size_t num_addresses, + bool stop_others, + uint32_t frame_idx = 0); + void AnalyzeStop(void); + +private: + + StackID m_stack_id; + lldb::addr_t m_step_from_insn; + lldb::break_id_t m_return_bp_id; + lldb::addr_t m_return_addr; + bool m_stepped_out; + bool m_should_stop; + bool m_ran_analyze; + bool m_explains_stop; + + typedef std::map<lldb::addr_t,lldb::break_id_t> until_collection; + until_collection m_until_points; + bool m_stop_others; + + void Clear(); + + friend lldb::ThreadPlanSP + Thread::QueueThreadPlanForStepUntil (bool abort_other_plans, + lldb::addr_t *address_list, + size_t num_addresses, + bool stop_others, + uint32_t frame_idx); + + // Need an appropriate marker for the current stack so we can tell step out + // from step in. + + DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepUntil); + +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanStepUntil_h_ diff --git a/include/lldb/Target/ThreadPlanTracer.h b/include/lldb/Target/ThreadPlanTracer.h new file mode 100644 index 0000000..4eb0c78 --- /dev/null +++ b/include/lldb/Target/ThreadPlanTracer.h @@ -0,0 +1,131 @@ +//===-- ThreadPlanTracer.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_ThreadPlanTracer_h_ +#define liblldb_ThreadPlanTracer_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Target/Thread.h" + +namespace lldb_private { + +class ThreadPlanTracer +{ +friend class ThreadPlan; + +public: + + typedef enum ThreadPlanTracerStyle + { + eLocation = 0, + eStateChange, + eCheckFrames, + ePython + } ThreadPlanTracerStyle; + ThreadPlanTracer (Thread &thread, lldb::StreamSP &stream_sp); + ThreadPlanTracer (Thread &thread); + + virtual ~ThreadPlanTracer() + { + } + + virtual void TracingStarted () + { + + } + + virtual void TracingEnded () + { + + } + + bool + EnableTracing(bool value) + { + bool old_value = m_enabled; + m_enabled = value; + if (old_value == false && value == true) + TracingStarted(); + else if (old_value == true && value == false) + TracingEnded(); + + return old_value; + } + + bool + TracingEnabled() + { + return m_enabled; + } + + bool + EnableSingleStep (bool value) + { + bool old_value = m_single_step; + m_single_step = value; + return old_value; + } + + bool + SingleStepEnabled () + { + return m_single_step; + } + +protected: + Thread &m_thread; + + Stream * + GetLogStream (); + + + + virtual void Log(); + +private: + bool + TracerExplainsStop (); + + bool m_single_step; + bool m_enabled; + lldb::StreamSP m_stream_sp; +}; + +class ThreadPlanAssemblyTracer : public ThreadPlanTracer +{ +public: + ThreadPlanAssemblyTracer (Thread &thread, lldb::StreamSP &stream_sp); + ThreadPlanAssemblyTracer (Thread &thread); + virtual ~ThreadPlanAssemblyTracer (); + virtual void TracingStarted (); + virtual void TracingEnded (); + virtual void Log(); +private: + + Disassembler * + GetDisassembler (); + + TypeFromUser + GetIntPointerType(); + + lldb::DisassemblerSP m_disassembler_sp; + TypeFromUser m_intptr_type; + std::vector<RegisterValue> m_register_values; + lldb::DataBufferSP m_buffer_sp; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadPlanTracer_h_ diff --git a/include/lldb/Target/ThreadSpec.h b/include/lldb/Target/ThreadSpec.h new file mode 100644 index 0000000..e0d3093 --- /dev/null +++ b/include/lldb/Target/ThreadSpec.h @@ -0,0 +1,155 @@ +//===-- ThreadSpec.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_ThreadSpec_h_ +#define liblldb_ThreadSpec_h_ + +#include <map> +#include <string> + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// Note: For now the thread spec has only fixed elements - +// Thread ID +// Thread Index +// Thread Name +// Thread Queue Name +// +// But if we need more generality, we can hang a key/value map off of this structure. +// That's why the thread matches spec test is done as a virtual method in Thread::MatchesSpec, +// since it is the native thread that would know how to interpret the keys. +// I was going to do the Queue Name this way out of sheer orneriness, but that seems a +// sufficiently general concept, so I put it in here on its own. + +class ThreadSpec +{ +public: + ThreadSpec (); + + ThreadSpec (const ThreadSpec &rhs); + + const ThreadSpec & + operator=(const ThreadSpec &rhs); + + void + SetIndex (uint32_t index) + { + m_index = index; + } + + void + SetTID (lldb::tid_t tid) + { + m_tid = tid; + } + + void + SetName (const char *name) + { + m_name = name; + } + + void + SetQueueName (const char *queue_name) + { + m_queue_name = queue_name; + } + + uint32_t + GetIndex () const + { + return m_index; + } + + lldb::tid_t + GetTID () const + { + return m_tid; + } + + const char * + GetName () const; + + const char * + GetQueueName () const; + + bool + TIDMatches (lldb::tid_t thread_id) const + { + if (m_tid == LLDB_INVALID_THREAD_ID || thread_id == LLDB_INVALID_THREAD_ID) + return true; + else + return thread_id == m_tid; + } + + bool + TIDMatches (Thread &thread) const; + + bool + IndexMatches (uint32_t index) const + { + if (m_index == UINT32_MAX || index == UINT32_MAX) + return true; + else + return index == m_index; + } + + bool + IndexMatches (Thread &thread) const; + + bool + NameMatches (const char *name) const + { + if (m_name.empty()) + return true; + else if (name == NULL) + return false; + else + return m_name == name; + } + + bool + NameMatches (Thread &thread) const; + + bool + QueueNameMatches (const char *queue_name) const + { + if (m_queue_name.empty()) + return true; + else if (queue_name == NULL) + return false; + else + return m_queue_name == queue_name; + } + + bool + QueueNameMatches (Thread &thread) const; + + bool + ThreadPassesBasicTests (Thread &thread) const; + + bool + HasSpecification () const; + + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + +protected: +private: + uint32_t m_index; + lldb::tid_t m_tid; + std::string m_name; + std::string m_queue_name; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSpec_h_ diff --git a/include/lldb/Target/UnixSignals.h b/include/lldb/Target/UnixSignals.h new file mode 100644 index 0000000..f47a90b --- /dev/null +++ b/include/lldb/Target/UnixSignals.h @@ -0,0 +1,144 @@ +//===-- UnixSignals.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_UnixSignals_h_ +#define lldb_UnixSignals_h_ + +// C Includes +// C++ Includes +#include <string> +#include <map> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" + +namespace lldb_private +{ + +class UnixSignals +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + UnixSignals(); + + virtual + ~UnixSignals(); + + const char * + GetSignalAsCString (int32_t signo) const; + + bool + SignalIsValid (int32_t signo) const; + + int32_t + GetSignalNumberFromName (const char *name) const; + + const char * + GetSignalInfo (int32_t signo, + bool &should_suppress, + bool &should_stop, + bool &should_notify) const; + + bool + GetShouldSuppress (int32_t signo) const; + + bool + SetShouldSuppress (int32_t signo, + bool value); + + bool + SetShouldSuppress (const char *signal_name, + bool value); + + bool + GetShouldStop (int32_t signo) const; + + bool + SetShouldStop (int32_t signo, + bool value); + bool + SetShouldStop (const char *signal_name, + bool value); + + bool + GetShouldNotify (int32_t signo) const; + + bool + SetShouldNotify (int32_t signo, bool value); + + bool + SetShouldNotify (const char *signal_name, + bool value); + + // These provide an iterator through the signals available on this system. + // Call GetFirstSignalNumber to get the first entry, then iterate on GetNextSignalNumber + // till you get back LLDB_INVALID_SIGNAL_NUMBER. + int32_t + GetFirstSignalNumber () const; + + int32_t + GetNextSignalNumber (int32_t current_signal) const; + + // We assume that the elements of this object are constant once it is constructed, + // since a process should never need to add or remove symbols as it runs. So don't + // call these functions anywhere but the constructor of your subclass of UnixSignals or in + // your Process Plugin's GetUnixSignals method before you return the UnixSignal object. + + void + AddSignal (int signo, + const char *name, + const char *short_name, + bool default_suppress, + bool default_stop, + bool default_notify, + const char *description); + + void + RemoveSignal (int signo); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from UnixSignals can see and modify these + //------------------------------------------------------------------ + + struct Signal + { + ConstString m_name; + ConstString m_short_name; + std::string m_description; + bool m_suppress:1, + m_stop:1, + m_notify:1; + + Signal (const char *name, + const char *short_name, + bool default_suppress, + bool default_stop, + bool default_notify, + const char *description); + + ~Signal () {} + }; + + void + Reset (); + + typedef std::map <int32_t, Signal> collection; + + collection m_signals; + + DISALLOW_COPY_AND_ASSIGN (UnixSignals); +}; + +} // Namespace lldb +#endif // lldb_UnixSignals_h_ diff --git a/include/lldb/Target/Unwind.h b/include/lldb/Target/Unwind.h new file mode 100644 index 0000000..7cda4ae --- /dev/null +++ b/include/lldb/Target/Unwind.h @@ -0,0 +1,120 @@ +//===-- Unwind.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_Unwind_h_ +#define liblldb_Unwind_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class Unwind +{ +protected: + //------------------------------------------------------------------ + // Classes that inherit from Unwind can see and modify these + //------------------------------------------------------------------ + Unwind(Thread &thread) : + m_thread (thread), + m_unwind_mutex() + { + } + +public: + virtual + ~Unwind() + { + } + + void + Clear() + { + Mutex::Locker locker(m_unwind_mutex); + DoClear(); + + } + + uint32_t + GetFrameCount() + { + Mutex::Locker locker(m_unwind_mutex); + return DoGetFrameCount(); + } + + uint32_t + GetFramesUpTo (uint32_t end_idx) + { + lldb::addr_t cfa; + lldb::addr_t pc; + uint32_t idx; + + for (idx = 0; idx < end_idx; idx++) + { + if (!DoGetFrameInfoAtIndex (idx, cfa, pc)) + { + break; + } + } + return idx; + } + + bool + GetFrameInfoAtIndex (uint32_t frame_idx, + lldb::addr_t& cfa, + lldb::addr_t& pc) + { + Mutex::Locker locker(m_unwind_mutex); + return DoGetFrameInfoAtIndex (frame_idx, cfa, pc); + } + + lldb::RegisterContextSP + CreateRegisterContextForFrame (StackFrame *frame) + { + Mutex::Locker locker(m_unwind_mutex); + return DoCreateRegisterContextForFrame (frame); + } + + Thread & + GetThread() + { + return m_thread; + } + +protected: + //------------------------------------------------------------------ + // Classes that inherit from Unwind can see and modify these + //------------------------------------------------------------------ + virtual void + DoClear() = 0; + + virtual uint32_t + DoGetFrameCount() = 0; + + virtual bool + DoGetFrameInfoAtIndex (uint32_t frame_idx, + lldb::addr_t& cfa, + lldb::addr_t& pc) = 0; + + virtual lldb::RegisterContextSP + DoCreateRegisterContextForFrame (StackFrame *frame) = 0; + + Thread &m_thread; + Mutex m_unwind_mutex; +private: + DISALLOW_COPY_AND_ASSIGN (Unwind); +}; + +} // namespace lldb_private + +#endif // liblldb_Unwind_h_ diff --git a/include/lldb/Target/UnwindAssembly.h b/include/lldb/Target/UnwindAssembly.h new file mode 100644 index 0000000..6a4ae0c --- /dev/null +++ b/include/lldb/Target/UnwindAssembly.h @@ -0,0 +1,58 @@ +//===-- UnwindAssembly.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_UnwindAssembly_h_ +#define utility_UnwindAssembly_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/PluginInterface.h" + +namespace lldb_private { + +class UnwindAssembly : + public PluginInterface +{ +public: + static UnwindAssembly* + FindPlugin (const ArchSpec &arch); + + virtual + ~UnwindAssembly(); + + virtual bool + GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, + Thread& thread, + UnwindPlan& unwind_plan) = 0; + + virtual bool + GetFastUnwindPlan (AddressRange& func, + Thread& thread, + UnwindPlan &unwind_plan) = 0; + + // thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch). + virtual bool + FirstNonPrologueInsn (AddressRange& func, + const lldb_private::ExecutionContext &exe_ctx, + Address& first_non_prologue_insn) = 0; + +protected: + UnwindAssembly (const ArchSpec &arch); + ArchSpec m_arch; + +private: + UnwindAssembly(); // Outlaw default constructor + DISALLOW_COPY_AND_ASSIGN (UnwindAssembly); +}; + +} // namespace lldb_private + +#endif //utility_UnwindAssembly_h_ + + diff --git a/include/lldb/Utility/AnsiTerminal.h b/include/lldb/Utility/AnsiTerminal.h new file mode 100644 index 0000000..036950c --- /dev/null +++ b/include/lldb/Utility/AnsiTerminal.h @@ -0,0 +1,156 @@ +//===---------------------AnsiTerminal.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + + +#define ANSI_FG_COLOR_BLACK 30 +#define ANSI_FG_COLOR_RED 31 +#define ANSI_FG_COLOR_GREEN 32 +#define ANSI_FG_COLOR_YELLOW 33 +#define ANSI_FG_COLOR_BLUE 34 +#define ANSI_FG_COLOR_PURPLE 35 +#define ANSI_FG_COLOR_CYAN 36 +#define ANSI_FG_COLOR_WHITE 37 + +#define ANSI_BG_COLOR_BLACK 40 +#define ANSI_BG_COLOR_RED 41 +#define ANSI_BG_COLOR_GREEN 42 +#define ANSI_BG_COLOR_YELLOW 43 +#define ANSI_BG_COLOR_BLUE 44 +#define ANSI_BG_COLOR_PURPLE 45 +#define ANSI_BG_COLOR_CYAN 46 +#define ANSI_BG_COLOR_WHITE 47 + +#define ANSI_SPECIAL_FRAMED 51 +#define ANSI_SPECIAL_ENCIRCLED 52 + +#define ANSI_CTRL_NORMAL 0 +#define ANSI_CTRL_BOLD 1 +#define ANSI_CTRL_FAINT 2 +#define ANSI_CTRL_ITALIC 3 +#define ANSI_CTRL_UNDERLINE 4 +#define ANSI_CTRL_SLOW_BLINK 5 +#define ANSI_CTRL_FAST_BLINK 6 +#define ANSI_CTRL_IMAGE_NEGATIVE 7 +#define ANSI_CTRL_CONCEAL 8 +#define ANSI_CTRL_CROSSED_OUT 9 + +#define ANSI_ESC_START "\033[" +#define ANSI_ESC_END "m" + +#define ANSI_1_CTRL(ctrl1) "\033["##ctrl1 ANSI_ESC_END +#define ANSI_2_CTRL(ctrl1,ctrl2) "\033["##ctrl1";"##ctrl2 ANSI_ESC_END + +namespace lldb_utility { + + namespace ansi { + const char *k_escape_start = "\033["; + const char *k_escape_end = "m"; + + const char *k_fg_black = "30"; + const char *k_fg_red = "31"; + const char *k_fg_green = "32"; + const char *k_fg_yellow = "33"; + const char *k_fg_blue = "34"; + const char *k_fg_purple = "35"; + const char *k_fg_cyan = "36"; + const char *k_fg_white = "37"; + + const char *k_bg_black = "40"; + const char *k_bg_red = "41"; + const char *k_bg_green = "42"; + const char *k_bg_yellow = "43"; + const char *k_bg_blue = "44"; + const char *k_bg_purple = "45"; + const char *k_bg_cyan = "46"; + const char *k_bg_white = "47"; + + const char *k_ctrl_normal = "0"; + const char *k_ctrl_bold = "1"; + const char *k_ctrl_faint = "2"; + const char *k_ctrl_italic = "3"; + const char *k_ctrl_underline = "4"; + const char *k_ctrl_slow_blink = "5"; + const char *k_ctrl_fast_blink = "6"; + const char *k_ctrl_negative = "7"; + const char *k_ctrl_conceal = "8"; + const char *k_ctrl_crossed_out = "9"; + + inline std::string + FormatAnsiTerminalCodes(const char *format, bool do_color = true) + { + // Convert "${ansi.XXX}" tokens to ansi values or clear them if do_color is false. + static const struct + { + const char *name; + const char *value; + } g_color_tokens[] = + { + #define _TO_STR2(_val) #_val + #define _TO_STR(_val) _TO_STR2(_val) + { "fg.black}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END }, + { "fg.red}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END }, + { "fg.green}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END }, + { "fg.yellow}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END }, + { "fg.blue}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END }, + { "fg.purple}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END }, + { "fg.cyan}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END }, + { "fg.white}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END }, + { "bg.black}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END }, + { "bg.red}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END }, + { "bg.green}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END }, + { "bg.yellow}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END }, + { "bg.blue}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END }, + { "bg.purple}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END }, + { "bg.cyan}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END }, + { "bg.white}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END }, + { "normal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END }, + { "bold}", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END }, + { "faint}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END }, + { "italic}", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END }, + { "underline}", ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END }, + { "slow-blink}", ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END }, + { "fast-blink}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END }, + { "negative}", ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END }, + { "conceal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END }, + { "crossed-out}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END }, + #undef _TO_STR + #undef _TO_STR2 + }; + static const char tok_hdr[] = "${ansi."; + + std::string fmt; + for (const char *p = format; *p; ++p) + { + const char *tok_start = strstr (p, tok_hdr); + if (!tok_start) + { + fmt.append (p, strlen(p)); + break; + } + + fmt.append (p, tok_start - p); + p = tok_start; + + const char *tok_str = tok_start + sizeof(tok_hdr) - 1; + for (size_t i = 0; i < sizeof(g_color_tokens) / sizeof(g_color_tokens[0]); ++i) + { + if (!strncmp (tok_str, g_color_tokens[i].name, strlen(g_color_tokens[i].name))) + { + if (do_color) + fmt.append (g_color_tokens[i].value); + p = tok_str + strlen (g_color_tokens[i].name) - 1; + break; + } + } + } + return fmt; + } + } +} diff --git a/include/lldb/Utility/CleanUp.h b/include/lldb/Utility/CleanUp.h new file mode 100644 index 0000000..ab15d19 --- /dev/null +++ b/include/lldb/Utility/CleanUp.h @@ -0,0 +1,322 @@ +//===-- CleanUp.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_CleanUp_h_ +#define liblldb_CleanUp_h_ + +#include "lldb/lldb-public.h" + +namespace lldb_utility { + +//---------------------------------------------------------------------- +// Templated class that guarantees that a cleanup callback function will +// be called. The cleanup function will be called once under the +// following conditions: +// - when the object goes out of scope +// - when the user explicitly calls clean. +// - the current value will be cleaned up when a new value is set using +// set(T value) as long as the current value hasn't already been cleaned. +// +// This class is designed to be used with simple types for type T (like +// file descriptors, opaque handles, pointers, etc). If more complex +// type T objects are desired, we need to probably specialize this class +// to take "const T&" for all input T parameters. Yet if a type T is +// complex already it might be better to build the cleanup funcionality +// into T. +// +// The cleanup function must take one argument that is of type T. +// The calback function return type is R. The return value is currently +// needed for "CallbackType". If there is an easy way to get around the +// need for the return value we can change this class. +// +// The two template parameters are: +// T - The variable type of value that will be stored and used as the +// sole argument for the cleanup callback. +// R - The return type for the cleanup function. +// +// EXAMPLES +// // Use with file handles that get opened where you want to close +// // them. Below we use "int open(const char *path, int oflag, ...)" +// // which returns an integer file descriptor. -1 is the invalid file +// // descriptor so to make an object that will call "int close(int fd)" +// // automatically we can use: +// +// CleanUp <int, int> fd(open("/tmp/a.txt", O_RDONLY, 0), -1, close); +// +// // malloc/free example +// CleanUp <void *, void> malloced_bytes(malloc(32), NULL, free); +//---------------------------------------------------------------------- +template <typename T, typename R = void> +class CleanUp +{ +public: + typedef T value_type; + typedef R (*CallbackType)(value_type); + + //---------------------------------------------------------------------- + // Constructor that sets the current value only. No values are + // considered to be invalid and the cleanup function will be called + // regardless of the value of m_current_value. + //---------------------------------------------------------------------- + CleanUp (value_type value, CallbackType callback) : + m_current_value (value), + m_invalid_value (), + m_callback (callback), + m_callback_called (false), + m_invalid_value_is_valid (false) + { + } + + //---------------------------------------------------------------------- + // Constructor that sets the current value and also the invalid value. + // The cleanup function will be called on "m_value" as long as it isn't + // equal to "m_invalid_value". + //---------------------------------------------------------------------- + CleanUp (value_type value, value_type invalid, CallbackType callback) : + m_current_value (value), + m_invalid_value (invalid), + m_callback (callback), + m_callback_called (false), + m_invalid_value_is_valid (true) + { + } + + //---------------------------------------------------------------------- + // Automatically cleanup when this object goes out of scope. + //---------------------------------------------------------------------- + ~CleanUp () + { + clean(); + } + + //---------------------------------------------------------------------- + // Access the value stored in this class + //---------------------------------------------------------------------- + value_type get() + { + return m_current_value; + } + + //---------------------------------------------------------------------- + // Access the value stored in this class + //---------------------------------------------------------------------- + const value_type + get() const + { + return m_current_value; + } + + //---------------------------------------------------------------------- + // Reset the owned value to "value". If a current value is valid and + // the cleanup callback hasn't been called, the previous value will + // be cleaned up (see void CleanUp::clean()). + //---------------------------------------------------------------------- + void + set (const value_type value) + { + // Cleanup the current value if needed + clean (); + // Now set the new value and mark our callback as not called + m_callback_called = false; + m_current_value = value; + } + + //---------------------------------------------------------------------- + // Checks is "m_current_value" is valid. The value is considered valid + // no invalid value was supplied during construction of this object or + // if an invalid value was supplied and "m_current_value" is not equal + // to "m_invalid_value". + // + // Returns true if "m_current_value" is valid, false otherwise. + //---------------------------------------------------------------------- + bool + is_valid() const + { + if (m_invalid_value_is_valid) + return m_current_value != m_invalid_value; + return true; + } + + //---------------------------------------------------------------------- + // This function will call the cleanup callback provided in the + // constructor one time if the value is considered valid (See is_valid()). + // This function sets m_callback_called to true so we don't call the + // cleanup callback multiple times on the same value. + //---------------------------------------------------------------------- + void + clean() + { + if (m_callback && !m_callback_called) + { + m_callback_called = true; + if (is_valid()) + m_callback(m_current_value); + } + } + + //---------------------------------------------------------------------- + // Cancels the cleanup that would have been called on "m_current_value" + // if it was valid. This function can be used to release the value + // contained in this object so ownership can be transfered to the caller. + //---------------------------------------------------------------------- + value_type + release () + { + m_callback_called = true; + return m_current_value; + } + +private: + value_type m_current_value; + const value_type m_invalid_value; + CallbackType m_callback; + bool m_callback_called; + bool m_invalid_value_is_valid; + + // Outlaw default constructor, copy constructor and the assignment operator + DISALLOW_COPY_AND_ASSIGN (CleanUp); +}; + +template <typename T, typename R, typename A0> +class CleanUp2 +{ +public: + typedef T value_type; + typedef R (*CallbackType)(value_type, A0); + + //---------------------------------------------------------------------- + // Constructor that sets the current value only. No values are + // considered to be invalid and the cleanup function will be called + // regardless of the value of m_current_value. + //---------------------------------------------------------------------- + CleanUp2 (value_type value, CallbackType callback, A0 arg) : + m_current_value (value), + m_invalid_value (), + m_callback (callback), + m_callback_called (false), + m_invalid_value_is_valid (false), + m_argument(arg) + { + } + + //---------------------------------------------------------------------- + // Constructor that sets the current value and also the invalid value. + // The cleanup function will be called on "m_value" as long as it isn't + // equal to "m_invalid_value". + //---------------------------------------------------------------------- + CleanUp2 (value_type value, value_type invalid, CallbackType callback, A0 arg) : + m_current_value (value), + m_invalid_value (invalid), + m_callback (callback), + m_callback_called (false), + m_invalid_value_is_valid (true), + m_argument(arg) + { + } + + //---------------------------------------------------------------------- + // Automatically cleanup when this object goes out of scope. + //---------------------------------------------------------------------- + ~CleanUp2 () + { + clean(); + } + + //---------------------------------------------------------------------- + // Access the value stored in this class + //---------------------------------------------------------------------- + value_type get() + { + return m_current_value; + } + + //---------------------------------------------------------------------- + // Access the value stored in this class + //---------------------------------------------------------------------- + const value_type + get() const + { + return m_current_value; + } + + //---------------------------------------------------------------------- + // Reset the owned value to "value". If a current value is valid and + // the cleanup callback hasn't been called, the previous value will + // be cleaned up (see void CleanUp::clean()). + //---------------------------------------------------------------------- + void + set (const value_type value) + { + // Cleanup the current value if needed + clean (); + // Now set the new value and mark our callback as not called + m_callback_called = false; + m_current_value = value; + } + + //---------------------------------------------------------------------- + // Checks is "m_current_value" is valid. The value is considered valid + // no invalid value was supplied during construction of this object or + // if an invalid value was supplied and "m_current_value" is not equal + // to "m_invalid_value". + // + // Returns true if "m_current_value" is valid, false otherwise. + //---------------------------------------------------------------------- + bool + is_valid() const + { + if (m_invalid_value_is_valid) + return m_current_value != m_invalid_value; + return true; + } + + //---------------------------------------------------------------------- + // This function will call the cleanup callback provided in the + // constructor one time if the value is considered valid (See is_valid()). + // This function sets m_callback_called to true so we don't call the + // cleanup callback multiple times on the same value. + //---------------------------------------------------------------------- + void + clean() + { + if (m_callback && !m_callback_called) + { + m_callback_called = true; + if (is_valid()) + m_callback(m_current_value, m_argument); + } + } + + //---------------------------------------------------------------------- + // Cancels the cleanup that would have been called on "m_current_value" + // if it was valid. This function can be used to release the value + // contained in this object so ownership can be transfered to the caller. + //---------------------------------------------------------------------- + value_type + release () + { + m_callback_called = true; + return m_current_value; + } + +private: + value_type m_current_value; + const value_type m_invalid_value; + CallbackType m_callback; + bool m_callback_called; + bool m_invalid_value_is_valid; + A0 m_argument; + + // Outlaw default constructor, copy constructor and the assignment operator + DISALLOW_COPY_AND_ASSIGN (CleanUp2); +}; + +} // namespace lldb_utility + +#endif // #ifndef liblldb_CleanUp_h_ diff --git a/include/lldb/Utility/PriorityPointerPair.h b/include/lldb/Utility/PriorityPointerPair.h new file mode 100644 index 0000000..49f0765 --- /dev/null +++ b/include/lldb/Utility/PriorityPointerPair.h @@ -0,0 +1,150 @@ +//===-- PriorityPointerPair.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_PriorityPointerPair_h_ +#define liblldb_PriorityPointerPair_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Utility/SharingPtr.h" + +namespace lldb_utility { + +//---------------------------------------------------------------------- +// A prioritized pair of SharedPtr<T>. One of the two pointers is high +// priority, the other is low priority. +// The Get() method always returns high, if *high != NULL, +// otherwise, low is returned (even if *low == NULL) +//---------------------------------------------------------------------- + +template<typename T> +class PriorityPointerPair +{ +public: + + typedef T& reference_type; + typedef T* pointer_type; + + typedef typename std::shared_ptr<T> T_SP; + + PriorityPointerPair() : + m_high(), + m_low() + {} + + PriorityPointerPair(pointer_type high, + pointer_type low) : + m_high(high), + m_low(low) + {} + + PriorityPointerPair(pointer_type low) : + m_high(), + m_low(low) + {} + + PriorityPointerPair(T_SP& high, + T_SP& low) : + m_high(high), + m_low(low) + {} + + PriorityPointerPair(T_SP& low) : + m_high(), + m_low(low) + {} + + void + SwapLow(pointer_type l) + { + m_low.swap(l); + } + + void + SwapHigh(pointer_type h) + { + m_high.swap(h); + } + + void + SwapLow(T_SP l) + { + m_low.swap(l); + } + + void + SwapHigh(T_SP h) + { + m_high.swap(h); + } + + T_SP + GetLow() + { + return m_low; + } + + T_SP + GetHigh() + { + return m_high; + } + + T_SP + Get() + { + if (m_high.get()) + return m_high; + return m_low; + } + + void + ResetHigh() + { + m_high.reset(); + } + + void + ResetLow() + { + m_low.reset(); + } + + void + Reset() + { + ResetLow(); + ResetHigh(); + } + + reference_type + operator*() const + { + return Get().operator*(); + } + + pointer_type + operator->() const + { + return Get().operator->(); + } + + ~PriorityPointerPair(); + +private: + + T_SP m_high; + T_SP m_low; + + DISALLOW_COPY_AND_ASSIGN (PriorityPointerPair); + +}; + +} // namespace lldb_utility + +#endif // #ifndef liblldb_PriorityPointerPair_h_ diff --git a/include/lldb/Utility/PseudoTerminal.h b/include/lldb/Utility/PseudoTerminal.h new file mode 100644 index 0000000..c79800f --- /dev/null +++ b/include/lldb/Utility/PseudoTerminal.h @@ -0,0 +1,266 @@ +//===-- PseudoTerminal.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_PseudoTerminal_h_ +#define liblldb_PseudoTerminal_h_ +#if defined(__cplusplus) + + +#include <fcntl.h> +#include <string> + +#include "lldb/lldb-defines.h" + +namespace lldb_utility { + +//---------------------------------------------------------------------- +/// @class PseudoTerminal PseudoTerminal.h "lldb/Core/PseudoTerminal.h" +/// @brief A pseudo terminal helper class. +/// +/// The pseudo terminal class abtracts the use of pseudo terminals on +/// the host system. +//---------------------------------------------------------------------- +class PseudoTerminal +{ +public: + enum + { + invalid_fd = -1 ///< Invalid file descriptor value + }; + + //------------------------------------------------------------------ + /// Default constructor + /// + /// Constructs this object with invalid master and slave file + /// descriptors. + //------------------------------------------------------------------ + PseudoTerminal (); + + //------------------------------------------------------------------ + /// Destructor + /// + /// The destructor will close the master and slave file descriptors + /// if they are valid and ownwership has not been released using + /// one of: + /// @li PseudoTerminal::ReleaseMasterFileDescriptor() + /// @li PseudoTerminal::ReleaseSaveFileDescriptor() + //------------------------------------------------------------------ + ~PseudoTerminal (); + + //------------------------------------------------------------------ + /// Close the master file descriptor if it is valid. + //------------------------------------------------------------------ + void + CloseMasterFileDescriptor (); + + //------------------------------------------------------------------ + /// Close the slave file descriptor if it is valid. + //------------------------------------------------------------------ + void + CloseSlaveFileDescriptor (); + + //------------------------------------------------------------------ + /// Fork a child process that uses pseudo terminals for its stdio. + /// + /// In the parent process, a call to this function results in a pid + /// being returned. If the pid is valid, the master file descriptor + /// can be used for read/write access to stdio of the child process. + /// + /// In the child process the stdin/stdout/stderr will already be + /// routed to the slave pseudo terminal and the master file + /// descriptor will be closed as it is no longer needed by the child + /// process. + /// + /// This class will close the file descriptors for the master/slave + /// when the destructor is called. The file handles can be released + /// using either: + /// @li PseudoTerminal::ReleaseMasterFileDescriptor() + /// @li PseudoTerminal::ReleaseSaveFileDescriptor() + /// + /// @param[out] error + /// An pointer to an error that can describe any errors that + /// occur. This can be NULL if no error status is desired. + /// + /// @return + /// @li \b Parent process: a child process ID that is greater + /// than zero, or -1 if the fork fails. + /// @li \b Child process: zero. + //------------------------------------------------------------------ + lldb::pid_t + Fork (char *error_str, size_t error_len); + + //------------------------------------------------------------------ + /// The master file descriptor accessor. + /// + /// This object retains ownership of the master file descriptor when + /// this accessor is used. Users can call the member function + /// PseudoTerminal::ReleaseMasterFileDescriptor() if this + /// object should release ownership of the slave file descriptor. + /// + /// @return + /// The master file descriptor, or PseudoTerminal::invalid_fd + /// if the master file descriptor is not currently valid. + /// + /// @see PseudoTerminal::ReleaseMasterFileDescriptor() + //------------------------------------------------------------------ + int + GetMasterFileDescriptor () const; + + //------------------------------------------------------------------ + /// The slave file descriptor accessor. + /// + /// This object retains ownership of the slave file descriptor when + /// this accessor is used. Users can call the member function + /// PseudoTerminal::ReleaseSlaveFileDescriptor() if this + /// object should release ownership of the slave file descriptor. + /// + /// @return + /// The slave file descriptor, or PseudoTerminal::invalid_fd + /// if the slave file descriptor is not currently valid. + /// + /// @see PseudoTerminal::ReleaseSlaveFileDescriptor() + //------------------------------------------------------------------ + int + GetSlaveFileDescriptor () const; + + //------------------------------------------------------------------ + /// Get the name of the slave pseudo terminal. + /// + /// A master pseudo terminal should already be valid prior to + /// calling this function. + /// + /// @param[out] error + /// An pointer to an error that can describe any errors that + /// occur. This can be NULL if no error status is desired. + /// + /// @return + /// The name of the slave pseudo terminal as a NULL terminated + /// C. This string that comes from static memory, so a copy of + /// the string should be made as subsequent calls can change + /// this value. NULL is returned if this object doesn't have + /// a valid master pseudo terminal opened or if the call to + /// \c ptsname() fails. + /// + /// @see PseudoTerminal::OpenFirstAvailableMaster() + //------------------------------------------------------------------ + const char* + GetSlaveName (char *error_str, size_t error_len) const; + + //------------------------------------------------------------------ + /// Open the first available pseudo terminal. + /// + /// Opens the first available pseudo terminal with \a oflag as the + /// permissions. The opened master file descriptor is stored in this + /// object and can be accessed by calling the + /// PseudoTerminal::GetMasterFileDescriptor() accessor. Clients + /// can call the PseudoTerminal::ReleaseMasterFileDescriptor() + /// accessor function if they wish to use the master file descriptor + /// beyond the lifespan of this object. + /// + /// If this object still has a valid master file descriptor when its + /// destructor is called, it will close it. + /// + /// @param[in] oflag + /// Flags to use when calling \c posix_openpt(\a oflag). + /// A value of "O_RDWR|O_NOCTTY" is suggested. + /// + /// @param[out] error + /// An pointer to an error that can describe any errors that + /// occur. This can be NULL if no error status is desired. + /// + /// @return + /// @li \b true when the a master files descriptor is + /// successfully opened. + /// @li \b false if anything goes wrong. + /// + /// @see PseudoTerminal::GetMasterFileDescriptor() + /// @see PseudoTerminal::ReleaseMasterFileDescriptor() + //------------------------------------------------------------------ + bool + OpenFirstAvailableMaster (int oflag, char *error_str, size_t error_len); + + //------------------------------------------------------------------ + /// Open the slave for the current master pseudo terminal. + /// + /// A master pseudo terminal should already be valid prior to + /// calling this function. The opened slave file descriptor is + /// stored in this object and can be accessed by calling the + /// PseudoTerminal::GetSlaveFileDescriptor() accessor. Clients + /// can call the PseudoTerminal::ReleaseSlaveFileDescriptor() + /// accessor function if they wish to use the slave file descriptor + /// beyond the lifespan of this object. + /// + /// If this object still has a valid slave file descriptor when its + /// destructor is called, it will close it. + /// + /// @param[in] oflag + /// Flags to use when calling \c open(\a oflag). + /// + /// @param[out] error + /// An pointer to an error that can describe any errors that + /// occur. This can be NULL if no error status is desired. + /// + /// @return + /// @li \b true when the a master files descriptor is + /// successfully opened. + /// @li \b false if anything goes wrong. + /// + /// @see PseudoTerminal::OpenFirstAvailableMaster() + /// @see PseudoTerminal::GetSlaveFileDescriptor() + /// @see PseudoTerminal::ReleaseSlaveFileDescriptor() + //------------------------------------------------------------------ + bool + OpenSlave (int oflag, char *error_str, size_t error_len); + + //------------------------------------------------------------------ + /// Release the master file descriptor. + /// + /// Releases ownership of the master pseudo terminal file descriptor + /// without closing it. The destructor for this class will close the + /// master file descriptor if the ownership isn't released using this + /// call and the master file descriptor has been opened. + /// + /// @return + /// The master file descriptor, or PseudoTerminal::invalid_fd + /// if the mast file descriptor is not currently valid. + //------------------------------------------------------------------ + int + ReleaseMasterFileDescriptor (); + + //------------------------------------------------------------------ + /// Release the slave file descriptor. + /// + /// Release ownership of the slave pseudo terminal file descriptor + /// without closing it. The destructor for this class will close the + /// slave file descriptor if the ownership isn't released using this + /// call and the slave file descriptor has been opened. + /// + /// @return + /// The slave file descriptor, or PseudoTerminal::invalid_fd + /// if the slave file descriptor is not currently valid. + //------------------------------------------------------------------ + int + ReleaseSlaveFileDescriptor (); + +protected: + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + int m_master_fd; ///< The file descriptor for the master. + int m_slave_fd; ///< The file descriptor for the slave. + +private: + DISALLOW_COPY_AND_ASSIGN (PseudoTerminal); + +}; + +} // namespace lldb + +#endif // #if defined(__cplusplus) +#endif // #ifndef liblldb_PseudoTerminal_h_ diff --git a/include/lldb/Utility/PythonPointer.h b/include/lldb/Utility/PythonPointer.h new file mode 100644 index 0000000..f782f7f --- /dev/null +++ b/include/lldb/Utility/PythonPointer.h @@ -0,0 +1,77 @@ +//===---------------------PythonPointer.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_PythonPointer_h_ +#define utility_PythonPointer_h_ + +#include <algorithm> + +#if defined (__APPLE__) +#include <Python/Python.h> +#else +#include <Python.h> +#endif + +namespace lldb_private { + +template<class T> +class PythonPointer +{ +public: + typedef PyObject* element_type; +private: + element_type* ptr_; + bool my_ref; +public: + + PythonPointer(element_type p, bool steal_ref = false) : + ptr_(p), + my_ref(!steal_ref) + { + if (my_ref) + Py_INCREF(ptr_); + } + + PythonPointer(const PythonPointer& r, bool steal_ref = false) : + ptr_(r.ptr_), + my_ref(!steal_ref) + { + if (my_ref) + Py_INCREF(ptr_); + } + + ~PythonPointer() + { + if (my_ref) + Py_XDECREF(ptr_); + } + + PythonPointer + StealReference() + { + return PythonPointer(ptr_,true); + } + + PythonPointer + DuplicateReference() + { + return PythonPointer(ptr_, false); + } + + element_type get() const {return ptr_;} + + bool IsNull() { return ptr_ == NULL; } + bool IsNone() { return ptr_ == Py_None; } + + operator PyObject* () { return ptr_; } +}; + +} // namespace lldb + +#endif // utility_PythonPointer_h_ diff --git a/include/lldb/Utility/Range.h b/include/lldb/Utility/Range.h new file mode 100644 index 0000000..1257adb --- /dev/null +++ b/include/lldb/Utility/Range.h @@ -0,0 +1,89 @@ +//===--------------------- Range.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_Range_h_ +#define utility_Range_h_ + +#include <stdint.h> +#include <algorithm> + +namespace lldb_utility { + +class Range +{ +public: + + typedef uint64_t ValueType; + + static const ValueType OPEN_END = UINT64_MAX; + + Range (const Range& rng); + + Range (ValueType low = 0, + ValueType high = OPEN_END); + + Range& + operator = (const Range& rhs); + + ValueType + GetLow () + { + return m_low; + } + + ValueType + GetHigh () + { + return m_high; + } + + void + SetLow (ValueType low) + { + m_low = low; + } + + void + SetHigh (ValueType high) + { + m_high = high; + } + + void + Flip (); + + void + Intersection (const Range& other); + + void + Union (const Range& other); + + typedef bool (*RangeCallback)(ValueType index); + + void + Iterate (RangeCallback callback); + + ValueType + GetSize (); + + bool + IsEmpty (); + +private: + + void + InitRange (); + + ValueType m_low; + ValueType m_high; +}; + +} // namespace lldb_private + +#endif // #ifndef utility_Range_h_ diff --git a/include/lldb/Utility/RefCounter.h b/include/lldb/Utility/RefCounter.h new file mode 100644 index 0000000..6daed54 --- /dev/null +++ b/include/lldb/Utility/RefCounter.h @@ -0,0 +1,56 @@ +//===-- RefCounter.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_RefCounter_h_ +#define liblldb_RefCounter_h_ + +#include "lldb/lldb-public.h" + +namespace lldb_utility { + +//---------------------------------------------------------------------- +// A simple reference counter object. You need an uint32_t* to use it +// Once that is in place, everyone who needs to ref-count, can say +// RefCounter ref(ptr); +// (of course, the pointer is a shared resource, and must be accessible to +// everyone who needs it). Synchronization is handled by RefCounter itself +// The counter is decreased each time a RefCounter to it goes out of scope +//---------------------------------------------------------------------- +class RefCounter +{ +public: + typedef uint32_t value_type; + + RefCounter(value_type* ctr); + + ~RefCounter(); + +private: + value_type* m_counter; + DISALLOW_COPY_AND_ASSIGN (RefCounter); + + template <class T> + inline T + increment(T* t) + { + return __sync_fetch_and_add(t, 1); + } + + template <class T> + inline T + decrement(T* t) + { + return __sync_fetch_and_add(t, -1); + } + +}; + +} // namespace lldb_utility + +#endif // #ifndef liblldb_RefCounter_h_ diff --git a/include/lldb/Utility/SharedCluster.h b/include/lldb/Utility/SharedCluster.h new file mode 100644 index 0000000..991af4b --- /dev/null +++ b/include/lldb/Utility/SharedCluster.h @@ -0,0 +1,108 @@ +//===------------------SharedCluster.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_SharedCluster_h_ +#define utility_SharedCluster_h_ + +#include "lldb/Utility/SharingPtr.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +namespace imp +{ + template <typename T> + class shared_ptr_refcount : public lldb_private::imp::shared_count + { + public: + template<class Y> shared_ptr_refcount (Y *in) : shared_count (0), manager(in) {} + + shared_ptr_refcount() : shared_count (0) {} + + virtual ~shared_ptr_refcount () + { + } + + virtual void on_zero_shared () + { + manager->DecrementRefCount(); + } + private: + T *manager; + }; + +} // namespace imp + +template <class T> +class ClusterManager +{ +public: + ClusterManager () : + m_objects(), + m_external_ref(0), + m_mutex(Mutex::eMutexTypeNormal) {} + + ~ClusterManager () + { + size_t n_items = m_objects.size(); + for (size_t i = 0; i < n_items; i++) + { + delete m_objects[i]; + } + // Decrement refcount should have been called on this ClusterManager, + // and it should have locked the mutex, now we will unlock it before + // we destroy it... + m_mutex.Unlock(); + } + + void ManageObject (T *new_object) + { + Mutex::Locker locker (m_mutex); + if (!ContainsObject(new_object)) + m_objects.push_back (new_object); + } + + typename lldb_private::SharingPtr<T> GetSharedPointer(T *desired_object) + { + { + Mutex::Locker locker (m_mutex); + m_external_ref++; + assert (ContainsObject(desired_object)); + } + return typename lldb_private::SharingPtr<T> (desired_object, new imp::shared_ptr_refcount<ClusterManager> (this)); + } + +private: + + bool ContainsObject (const T *desired_object) + { + typename std::vector<T *>::iterator pos, end = m_objects.end(); + pos = std::find(m_objects.begin(), end, desired_object); + return pos != end; + } + + void DecrementRefCount () + { + m_mutex.Lock(); + m_external_ref--; + if (m_external_ref == 0) + delete this; + else + m_mutex.Unlock(); + } + + friend class imp::shared_ptr_refcount<ClusterManager>; + + std::vector<T *> m_objects; + int m_external_ref; + Mutex m_mutex; +}; + +} // namespace lldb_private +#endif // utility_SharedCluster_h_ diff --git a/include/lldb/Utility/SharingPtr.h b/include/lldb/Utility/SharingPtr.h new file mode 100644 index 0000000..814b54b --- /dev/null +++ b/include/lldb/Utility/SharingPtr.h @@ -0,0 +1,816 @@ +//===---------------------SharingPtr.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_SharingPtr_h_ +#define utility_SharingPtr_h_ + +#include <algorithm> +#include <memory> + +//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT +#if defined (ENABLE_SP_LOGGING) + +extern "C" void track_sp (void *sp_this, void *ptr, long count); + +#endif + +namespace lldb_private { + +namespace imp { + +template <class T> +inline T +increment(T& t) +{ + return __sync_add_and_fetch(&t, 1); +} + +template <class T> +inline T +decrement(T& t) +{ + return __sync_add_and_fetch(&t, -1); +} + +class shared_count +{ + shared_count(const shared_count&); + shared_count& operator=(const shared_count&); + +protected: + long shared_owners_; + virtual ~shared_count(); +private: + virtual void on_zero_shared() = 0; + +public: + explicit shared_count(long refs = 0) + : shared_owners_(refs) {} + + void add_shared(); + void release_shared(); + long use_count() const {return shared_owners_ + 1;} +}; + +template <class T> +class shared_ptr_pointer + : public shared_count +{ + T data_; +public: + shared_ptr_pointer(T p) + : data_(p) {} + +private: + virtual void on_zero_shared(); + + // Outlaw copy constructor and assignment operator to keep effictive C++ + // warnings down to a minumum + shared_ptr_pointer (const shared_ptr_pointer &); + shared_ptr_pointer & operator=(const shared_ptr_pointer &); +}; + +template <class T> +void +shared_ptr_pointer<T>::on_zero_shared() +{ + delete data_; +} + +template <class T> +class shared_ptr_emplace + : public shared_count +{ + T data_; +public: + + shared_ptr_emplace() + : data_() {} + + template <class A0> + shared_ptr_emplace(A0& a0) + : data_(a0) {} + + template <class A0, class A1> + shared_ptr_emplace(A0& a0, A1& a1) + : data_(a0, a1) {} + + template <class A0, class A1, class A2> + shared_ptr_emplace(A0& a0, A1& a1, A2& a2) + : data_(a0, a1, a2) {} + + template <class A0, class A1, class A2, class A3> + shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3) + : data_(a0, a1, a2, a3) {} + + template <class A0, class A1, class A2, class A3, class A4> + shared_ptr_emplace(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) + : data_(a0, a1, a2, a3, a4) {} + +private: + virtual void on_zero_shared(); +public: + T* get() {return &data_;} +}; + +template <class T> +void +shared_ptr_emplace<T>::on_zero_shared() +{ +} + +} // namespace + +template<class T> +class SharingPtr +{ +public: + typedef T element_type; +private: + element_type* ptr_; + imp::shared_count* cntrl_; + + struct nat {int for_bool_;}; +public: + SharingPtr(); + template<class Y> explicit SharingPtr(Y* p); + template<class Y> explicit SharingPtr(Y* p, imp::shared_count *ctrl_block); + template<class Y> SharingPtr(const SharingPtr<Y>& r, element_type *p); + SharingPtr(const SharingPtr& r); + template<class Y> + SharingPtr(const SharingPtr<Y>& r); + + ~SharingPtr(); + + SharingPtr& operator=(const SharingPtr& r); + template<class Y> SharingPtr& operator=(const SharingPtr<Y>& r); + + void swap(SharingPtr& r); + void reset(); + template<class Y> void reset(Y* p); + + element_type* get() const {return ptr_;} + element_type& operator*() const {return *ptr_;} + element_type* operator->() const {return ptr_;} + long use_count() const {return cntrl_ ? cntrl_->use_count() : 0;} + bool unique() const {return use_count() == 1;} + bool empty() const {return cntrl_ == 0;} + operator nat*() const {return (nat*)get();} + + static SharingPtr<T> make_shared(); + + template<class A0> + static SharingPtr<T> make_shared(A0&); + + template<class A0, class A1> + static SharingPtr<T> make_shared(A0&, A1&); + + template<class A0, class A1, class A2> + static SharingPtr<T> make_shared(A0&, A1&, A2&); + + template<class A0, class A1, class A2, class A3> + static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&); + + template<class A0, class A1, class A2, class A3, class A4> + static SharingPtr<T> make_shared(A0&, A1&, A2&, A3&, A4&); + +private: + + template <class U> friend class SharingPtr; +}; + +template<class T> +inline +SharingPtr<T>::SharingPtr() + : ptr_(0), + cntrl_(0) +{ +} + +template<class T> +template<class Y> +SharingPtr<T>::SharingPtr(Y* p) + : ptr_(p), cntrl_(0) +{ + std::unique_ptr<Y> hold(p); + typedef imp::shared_ptr_pointer<Y*> _CntrlBlk; + cntrl_ = new _CntrlBlk(p); + hold.release(); +} + +template<class T> +template<class Y> +SharingPtr<T>::SharingPtr(Y* p, imp::shared_count *cntrl_block) + : ptr_(p), cntrl_(cntrl_block) +{ +} + +template<class T> +template<class Y> +inline +SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r, element_type *p) + : ptr_(p), + cntrl_(r.cntrl_) +{ + if (cntrl_) + cntrl_->add_shared(); +} + +template<class T> +inline +SharingPtr<T>::SharingPtr(const SharingPtr& r) + : ptr_(r.ptr_), + cntrl_(r.cntrl_) +{ + if (cntrl_) + cntrl_->add_shared(); +} + +template<class T> +template<class Y> +inline +SharingPtr<T>::SharingPtr(const SharingPtr<Y>& r) + : ptr_(r.ptr_), + cntrl_(r.cntrl_) +{ + if (cntrl_) + cntrl_->add_shared(); +} + +template<class T> +SharingPtr<T>::~SharingPtr() +{ + if (cntrl_) + cntrl_->release_shared(); +} + +template<class T> +inline +SharingPtr<T>& +SharingPtr<T>::operator=(const SharingPtr& r) +{ + SharingPtr(r).swap(*this); + return *this; +} + +template<class T> +template<class Y> +inline +SharingPtr<T>& +SharingPtr<T>::operator=(const SharingPtr<Y>& r) +{ + SharingPtr(r).swap(*this); + return *this; +} + +template<class T> +inline +void +SharingPtr<T>::swap(SharingPtr& r) +{ + std::swap(ptr_, r.ptr_); + std::swap(cntrl_, r.cntrl_); +} + +template<class T> +inline +void +SharingPtr<T>::reset() +{ + SharingPtr().swap(*this); +} + +template<class T> +template<class Y> +inline +void +SharingPtr<T>::reset(Y* p) +{ + SharingPtr(p).swap(*this); +} + +template<class T> +SharingPtr<T> +SharingPtr<T>::make_shared() +{ + typedef imp::shared_ptr_emplace<T> CntrlBlk; + SharingPtr<T> r; + r.cntrl_ = new CntrlBlk(); + r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get(); + return r; +} + +template<class T> +template<class A0> +SharingPtr<T> +SharingPtr<T>::make_shared(A0& a0) +{ + typedef imp::shared_ptr_emplace<T> CntrlBlk; + SharingPtr<T> r; + r.cntrl_ = new CntrlBlk(a0); + r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get(); + return r; +} + +template<class T> +template<class A0, class A1> +SharingPtr<T> +SharingPtr<T>::make_shared(A0& a0, A1& a1) +{ + typedef imp::shared_ptr_emplace<T> CntrlBlk; + SharingPtr<T> r; + r.cntrl_ = new CntrlBlk(a0, a1); + r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get(); + return r; +} + +template<class T> +template<class A0, class A1, class A2> +SharingPtr<T> +SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2) +{ + typedef imp::shared_ptr_emplace<T> CntrlBlk; + SharingPtr<T> r; + r.cntrl_ = new CntrlBlk(a0, a1, a2); + r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get(); + return r; +} + +template<class T> +template<class A0, class A1, class A2, class A3> +SharingPtr<T> +SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3) +{ + typedef imp::shared_ptr_emplace<T> CntrlBlk; + SharingPtr<T> r; + r.cntrl_ = new CntrlBlk(a0, a1, a2, a3); + r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get(); + return r; +} + +template<class T> +template<class A0, class A1, class A2, class A3, class A4> +SharingPtr<T> +SharingPtr<T>::make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) +{ + typedef imp::shared_ptr_emplace<T> CntrlBlk; + SharingPtr<T> r; + r.cntrl_ = new CntrlBlk(a0, a1, a2, a3, a4); + r.ptr_ = static_cast<CntrlBlk*>(r.cntrl_)->get(); + return r; +} + +template<class T> +inline +SharingPtr<T> +make_shared() +{ + return SharingPtr<T>::make_shared(); +} + +template<class T, class A0> +inline +SharingPtr<T> +make_shared(A0& a0) +{ + return SharingPtr<T>::make_shared(a0); +} + +template<class T, class A0, class A1> +inline +SharingPtr<T> +make_shared(A0& a0, A1& a1) +{ + return SharingPtr<T>::make_shared(a0, a1); +} + +template<class T, class A0, class A1, class A2> +inline +SharingPtr<T> +make_shared(A0& a0, A1& a1, A2& a2) +{ + return SharingPtr<T>::make_shared(a0, a1, a2); +} + +template<class T, class A0, class A1, class A2, class A3> +inline +SharingPtr<T> +make_shared(A0& a0, A1& a1, A2& a2, A3& a3) +{ + return SharingPtr<T>::make_shared(a0, a1, a2, a3); +} + +template<class T, class A0, class A1, class A2, class A3, class A4> +inline +SharingPtr<T> +make_shared(A0& a0, A1& a1, A2& a2, A3& a3, A4& a4) +{ + return SharingPtr<T>::make_shared(a0, a1, a2, a3, a4); +} + + +template<class T, class U> +inline +bool +operator==(const SharingPtr<T>& __x, const SharingPtr<U>& __y) +{ + return __x.get() == __y.get(); +} + +template<class T, class U> +inline +bool +operator!=(const SharingPtr<T>& __x, const SharingPtr<U>& __y) +{ + return !(__x == __y); +} + +template<class T, class U> +inline +bool +operator<(const SharingPtr<T>& __x, const SharingPtr<U>& __y) +{ + return __x.get() < __y.get(); +} + +template<class T> +inline +void +swap(SharingPtr<T>& __x, SharingPtr<T>& __y) +{ + __x.swap(__y); +} + +template<class T, class U> +inline +SharingPtr<T> +static_pointer_cast(const SharingPtr<U>& r) +{ + return SharingPtr<T>(r, static_cast<T*>(r.get())); +} + +template<class T, class U> +SharingPtr<T> +const_pointer_cast(const SharingPtr<U>& r) +{ + return SharingPtr<T>(r, const_cast<T*>(r.get())); +} + +template <class T> +class LoggingSharingPtr + : public SharingPtr<T> +{ + typedef SharingPtr<T> base; + +public: + typedef void (*Callback)(void*, const LoggingSharingPtr&, bool action); + // action: false means increment just happened + // true means decrement is about to happen + +private: + Callback cb_; + void* baton_; + +public: + LoggingSharingPtr() : cb_(0), baton_(0) {} + LoggingSharingPtr(Callback cb, void* baton) + : cb_(cb), baton_(baton) + { + if (cb_) + cb_(baton_, *this, false); + } + + template <class Y> + LoggingSharingPtr(Y* p) + : base(p), cb_(0), baton_(0) {} + + template <class Y> + LoggingSharingPtr(Y* p, Callback cb, void* baton) + : base(p), cb_(cb), baton_(baton) + { + if (cb_) + cb_(baton_, *this, false); + } + + ~LoggingSharingPtr() + { + if (cb_) + cb_(baton_, *this, true); + } + + LoggingSharingPtr(const LoggingSharingPtr& p) + : base(p), cb_(p.cb_), baton_(p.baton_) + { + if (cb_) + cb_(baton_, *this, false); + } + + LoggingSharingPtr& operator=(const LoggingSharingPtr& p) + { + if (cb_) + cb_(baton_, *this, true); + base::operator=(p); + cb_ = p.cb_; + baton_ = p.baton_; + if (cb_) + cb_(baton_, *this, false); + return *this; + } + + void reset() + { + if (cb_) + cb_(baton_, *this, true); + base::reset(); + } + + template <class Y> + void reset(Y* p) + { + if (cb_) + cb_(baton_, *this, true); + base::reset(p); + if (cb_) + cb_(baton_, *this, false); + } + + void SetCallback(Callback cb, void* baton) + { + cb_ = cb; + baton_ = baton; + } + + void ClearCallback() + { + cb_ = 0; + baton_ = 0; + } +}; + + +template <class T> +class IntrusiveSharingPtr; + +template <class T> +class ReferenceCountedBase +{ +public: + explicit ReferenceCountedBase() + : shared_owners_(-1) + { + } + + void + add_shared(); + + void + release_shared(); + + long + use_count() const + { + return shared_owners_ + 1; + } + +protected: + long shared_owners_; + + friend class IntrusiveSharingPtr<T>; + +private: + ReferenceCountedBase(const ReferenceCountedBase&); + ReferenceCountedBase& operator=(const ReferenceCountedBase&); +}; + + template <class T> + void + lldb_private::ReferenceCountedBase<T>::add_shared() + { + imp::increment(shared_owners_); + } + + template <class T> + void + lldb_private::ReferenceCountedBase<T>::release_shared() + { + if (imp::decrement(shared_owners_) == -1) + delete static_cast<T*>(this); + } + + +template <class T> +class ReferenceCountedBaseVirtual : public imp::shared_count +{ +public: + explicit ReferenceCountedBaseVirtual () : + imp::shared_count(-1) + { + } + + virtual + ~ReferenceCountedBaseVirtual () + { + } + + virtual void on_zero_shared (); + +}; + +template <class T> +void +ReferenceCountedBaseVirtual<T>::on_zero_shared() +{ +} + +template <typename T> +class IntrusiveSharingPtr +{ +public: + typedef T element_type; + + explicit + IntrusiveSharingPtr () : + ptr_(0) + { + } + + explicit + IntrusiveSharingPtr (T* ptr) : + ptr_(ptr) + { + add_shared(); + } + + IntrusiveSharingPtr (const IntrusiveSharingPtr& rhs) : + ptr_(rhs.ptr_) + { + add_shared(); + } + + template <class X> + IntrusiveSharingPtr (const IntrusiveSharingPtr<X>& rhs) + : ptr_(rhs.get()) + { + add_shared(); + } + + IntrusiveSharingPtr& + operator= (const IntrusiveSharingPtr& rhs) + { + reset(rhs.get()); + return *this; + } + + template <class X> IntrusiveSharingPtr& + operator= (const IntrusiveSharingPtr<X>& rhs) + { + reset(rhs.get()); + return *this; + } + + IntrusiveSharingPtr& + operator= (T *ptr) + { + reset(ptr); + return *this; + } + + ~IntrusiveSharingPtr() + { + release_shared(); +#if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE) + // NULL out the pointer in objects which can help with leaks detection. + // We don't enable this for LLDB_CONFIGURATION_BUILD_AND_INTEGRATION or + // when none of the LLDB_CONFIGURATION_XXX macros are defined since + // those would be builds for release. But for debug and release builds + // that are for development, we NULL out the pointers to catch potential + // issues. + ptr_ = NULL; +#endif // #if defined (LLDB_CONFIGURATION_DEBUG) || defined (LLDB_CONFIGURATION_RELEASE) + } + + T& + operator*() const + { + return *ptr_; + } + + T* + operator->() const + { + return ptr_; + } + + T* + get() const + { + return ptr_; + } + + operator bool() const + { + return ptr_ != 0; + } + + void + swap (IntrusiveSharingPtr& rhs) + { + std::swap(ptr_, rhs.ptr_); +#if defined (ENABLE_SP_LOGGING) + track_sp (this, ptr_, use_count()); + track_sp (&rhs, rhs.ptr_, rhs.use_count()); +#endif + } + + void + reset(T* ptr = NULL) + { + IntrusiveSharingPtr(ptr).swap(*this); + } + + long + use_count () const + { + if (ptr_) + return ptr_->use_count(); + return 0; + } + + bool + unique () const + { + return use_count () == 1; + } + +private: + element_type *ptr_; + + void + add_shared() + { + if (ptr_) + { + ptr_->add_shared(); +#if defined (ENABLE_SP_LOGGING) + track_sp (this, ptr_, ptr_->use_count()); +#endif + } + } + void + release_shared() + { + if (ptr_) + { +#if defined (ENABLE_SP_LOGGING) + track_sp (this, NULL, ptr_->use_count() - 1); +#endif + ptr_->release_shared(); + } + } +}; + +template<class T, class U> +inline bool operator== (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs) +{ + return lhs.get() == rhs.get(); +} + +template<class T, class U> +inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, const IntrusiveSharingPtr<U>& rhs) +{ + return lhs.get() != rhs.get(); +} + +template<class T, class U> +inline bool operator== (const IntrusiveSharingPtr<T>& lhs, U* rhs) +{ + return lhs.get() == rhs; +} + +template<class T, class U> +inline bool operator!= (const IntrusiveSharingPtr<T>& lhs, U* rhs) +{ + return lhs.get() != rhs; +} + +template<class T, class U> +inline bool operator== (T* lhs, const IntrusiveSharingPtr<U>& rhs) +{ + return lhs == rhs.get(); +} + +template<class T, class U> +inline bool operator!= (T* lhs, const IntrusiveSharingPtr<U>& rhs) +{ + return lhs != rhs.get(); +} + +} // namespace lldb_private + +#endif // utility_SharingPtr_h_ diff --git a/include/lldb/Utility/Utils.h b/include/lldb/Utility/Utils.h new file mode 100644 index 0000000..46bc184 --- /dev/null +++ b/include/lldb/Utility/Utils.h @@ -0,0 +1,22 @@ +//===-- Utils.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef utility_Utils_h_ +#define utility_Utils_h_ + +// These utilities have llvm namespace. +#include "llvm/ADT/STLExtras.h" + +namespace lldb_private { + +// Add lldb utilities here. + +} // namespace lldb_private + +#endif // utility_Utils diff --git a/include/lldb/lldb-defines.h b/include/lldb/lldb-defines.h new file mode 100644 index 0000000..3318aa1 --- /dev/null +++ b/include/lldb/lldb-defines.h @@ -0,0 +1,125 @@ +//===-- lldb-defines.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_lldb_defines_h_ +#define LLDB_lldb_defines_h_ + +#include "lldb/lldb-types.h" + +#if !defined(UINT32_MAX) + #define UINT32_MAX 4294967295U +#endif + +#if !defined(UINT64_MAX) + #define UINT64_MAX 18446744073709551615ULL +#endif + +//---------------------------------------------------------------------- +// LLDB version +// +// A build script phase can modify this version number if needed. +//---------------------------------------------------------------------- +//#define LLDB_VERSION +//#define LLDB_REVISION +//#define LLDB_VERSION_STRING + +//---------------------------------------------------------------------- +// LLDB defines +//---------------------------------------------------------------------- +#define LLDB_GENERIC_ERROR UINT32_MAX + +//---------------------------------------------------------------------- +// Breakpoints +//---------------------------------------------------------------------- +#define LLDB_INVALID_BREAK_ID 0 +#define LLDB_DEFAULT_BREAK_SIZE 0 +#define LLDB_BREAK_ID_IS_VALID(bid) ((bid) != (LLDB_INVALID_BREAK_ID)) +#define LLDB_BREAK_ID_IS_INTERNAL(bid) ((bid) < 0) + +//---------------------------------------------------------------------- +// Watchpoints +//---------------------------------------------------------------------- +#define LLDB_INVALID_WATCH_ID 0 +#define LLDB_WATCH_ID_IS_VALID(uid) ((uid) != (LLDB_INVALID_WATCH_ID)) +#define LLDB_WATCH_TYPE_READ (1u << 0) +#define LLDB_WATCH_TYPE_WRITE (1u << 1) +#define LLDB_WATCH_TYPE_IS_VALID(type) ((type | LLDB_WATCH_TYPE_READ) || (type | LLDB_WATCH_TYPE_WRITE)) + +//---------------------------------------------------------------------- +// Generic Register Numbers +//---------------------------------------------------------------------- +#define LLDB_REGNUM_GENERIC_PC 0 // Program Counter +#define LLDB_REGNUM_GENERIC_SP 1 // Stack Pointer +#define LLDB_REGNUM_GENERIC_FP 2 // Frame Pointer +#define LLDB_REGNUM_GENERIC_RA 3 // Return Address +#define LLDB_REGNUM_GENERIC_FLAGS 4 // Processor flags register +#define LLDB_REGNUM_GENERIC_ARG1 5 // The register that would contain pointer size or less argument 1 (if any) +#define LLDB_REGNUM_GENERIC_ARG2 6 // The register that would contain pointer size or less argument 2 (if any) +#define LLDB_REGNUM_GENERIC_ARG3 7 // The register that would contain pointer size or less argument 3 (if any) +#define LLDB_REGNUM_GENERIC_ARG4 8 // The register that would contain pointer size or less argument 4 (if any) +#define LLDB_REGNUM_GENERIC_ARG5 9 // The register that would contain pointer size or less argument 5 (if any) +#define LLDB_REGNUM_GENERIC_ARG6 10 // The register that would contain pointer size or less argument 6 (if any) +#define LLDB_REGNUM_GENERIC_ARG7 11 // The register that would contain pointer size or less argument 7 (if any) +#define LLDB_REGNUM_GENERIC_ARG8 12 // The register that would contain pointer size or less argument 8 (if any) +//--------------------------------------------------------------------- +/// Invalid value definitions +//---------------------------------------------------------------------- +#define LLDB_INVALID_ADDRESS UINT64_MAX +#define LLDB_INVALID_INDEX32 UINT32_MAX +#define LLDB_INVALID_IVAR_OFFSET UINT32_MAX +#define LLDB_INVALID_IMAGE_TOKEN UINT32_MAX +#define LLDB_INVALID_REGNUM UINT32_MAX +#define LLDB_INVALID_UID UINT64_MAX +#define LLDB_INVALID_PROCESS_ID 0 +#define LLDB_INVALID_THREAD_ID 0 +#define LLDB_INVALID_FRAME_ID UINT32_MAX +#define LLDB_INVALID_SIGNAL_NUMBER INT32_MAX +#define LLDB_INVALID_OFFSET UINT64_MAX // Must match max of lldb::offset_t + +//---------------------------------------------------------------------- +/// CPU Type defintions +//---------------------------------------------------------------------- +#define LLDB_ARCH_DEFAULT "systemArch" +#define LLDB_ARCH_DEFAULT_32BIT "systemArch32" +#define LLDB_ARCH_DEFAULT_64BIT "systemArch64" +#define LLDB_INVALID_CPUTYPE (0xFFFFFFFEu) + +//---------------------------------------------------------------------- +/// Option Set defintions +//---------------------------------------------------------------------- +// FIXME: I'm sure there's some #define magic that can create all 32 sets on the +// fly. That would have the added benefit of making this unreadable. +#define LLDB_MAX_NUM_OPTION_SETS 32 +#define LLDB_OPT_SET_ALL 0xFFFFFFFFU +#define LLDB_OPT_SET_1 (1U << 0) +#define LLDB_OPT_SET_2 (1U << 1) +#define LLDB_OPT_SET_3 (1U << 2) +#define LLDB_OPT_SET_4 (1U << 3) +#define LLDB_OPT_SET_5 (1U << 4) +#define LLDB_OPT_SET_6 (1U << 5) +#define LLDB_OPT_SET_7 (1U << 6) +#define LLDB_OPT_SET_8 (1U << 7) +#define LLDB_OPT_SET_9 (1U << 8) +#define LLDB_OPT_SET_10 (1U << 9) +#define LLDB_OPT_SET_FROM_TO(A, B) (((1U << (B)) - 1) ^ (((1U << (A))-1) >> 1)) + +#if defined(__cplusplus) + +//---------------------------------------------------------------------- +/// @def DISALLOW_COPY_AND_ASSIGN(TypeName) +/// Macro definition for easily disallowing copy constructor and +/// assignment operators in C++ classes. +//---------------------------------------------------------------------- +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + const TypeName& operator=(const TypeName&) + +#endif // #if defined(__cplusplus) + +#endif // LLDB_lldb_defines_h_ diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h new file mode 100644 index 0000000..6ec5ed6 --- /dev/null +++ b/include/lldb/lldb-enumerations.h @@ -0,0 +1,685 @@ +//===-- lldb-enumerations.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_lldb_enumerations_h_ +#define LLDB_lldb_enumerations_h_ + +namespace lldb { + + //---------------------------------------------------------------------- + // Process and Thread States + //---------------------------------------------------------------------- + typedef enum StateType + { + eStateInvalid = 0, + eStateUnloaded, ///< Process is object is valid, but not currently loaded + eStateConnected, ///< Process is connected to remote debug services, but not launched or attached to anything yet + eStateAttaching, ///< Process is currently trying to attach + eStateLaunching, ///< Process is in the process of launching + eStateStopped, ///< Process or thread is stopped and can be examined. + eStateRunning, ///< Process or thread is running and can't be examined. + eStateStepping, ///< Process or thread is in the process of stepping and can not be examined. + eStateCrashed, ///< Process or thread has crashed and can be examined. + eStateDetached, ///< Process has been detached and can't be examined. + eStateExited, ///< Process has exited and can't be examined. + eStateSuspended ///< Process or thread is in a suspended state as far + ///< as the debugger is concerned while other processes + ///< or threads get the chance to run. + } StateType; + + //---------------------------------------------------------------------- + // Launch Flags + //---------------------------------------------------------------------- + typedef enum LaunchFlags + { + eLaunchFlagNone = 0u, + eLaunchFlagExec = (1u << 0), ///< Exec when launching and turn the calling process into a new process + eLaunchFlagDebug = (1u << 1), ///< Stop as soon as the process launches to allow the process to be debugged + eLaunchFlagStopAtEntry = (1u << 2), ///< Stop at the program entry point instead of auto-continuing when launching or attaching at entry point + eLaunchFlagDisableASLR = (1u << 3), ///< Disable Address Space Layout Randomization + eLaunchFlagDisableSTDIO = (1u << 4), ///< Disable stdio for inferior process (e.g. for a GUI app) + eLaunchFlagLaunchInTTY = (1u << 5), ///< Launch the process in a new TTY if supported by the host + eLaunchFlagLaunchInShell= (1u << 6), ///< Launch the process inside a shell to get shell expansion + eLaunchFlagLaunchInSeparateProcessGroup = (1u << 7) ///< Launch the process in a separate process group + } LaunchFlags; + + //---------------------------------------------------------------------- + // Thread Run Modes + //---------------------------------------------------------------------- + typedef enum RunMode { + eOnlyThisThread, + eAllThreads, + eOnlyDuringStepping + } RunMode; + + //---------------------------------------------------------------------- + // Byte ordering definitions + //---------------------------------------------------------------------- + typedef enum ByteOrder + { + eByteOrderInvalid = 0, + eByteOrderBig = 1, + eByteOrderPDP = 2, + eByteOrderLittle = 4 + } ByteOrder; + + //---------------------------------------------------------------------- + // Register encoding definitions + //---------------------------------------------------------------------- + typedef enum Encoding + { + eEncodingInvalid = 0, + eEncodingUint, // unsigned integer + eEncodingSint, // signed integer + eEncodingIEEE754, // float + eEncodingVector // vector registers + } Encoding; + + //---------------------------------------------------------------------- + // Display format definitions + //---------------------------------------------------------------------- + typedef enum Format + { + eFormatDefault = 0, + eFormatInvalid = 0, + eFormatBoolean, + eFormatBinary, + eFormatBytes, + eFormatBytesWithASCII, + eFormatChar, + eFormatCharPrintable, // Only printable characters, space if not printable + eFormatComplex, // Floating point complex type + eFormatComplexFloat = eFormatComplex, + eFormatCString, // NULL terminated C strings + eFormatDecimal, + eFormatEnum, + eFormatHex, + eFormatHexUppercase, + eFormatFloat, + eFormatOctal, + eFormatOSType, // OS character codes encoded into an integer 'PICT' 'text' etc... + eFormatUnicode16, + eFormatUnicode32, + eFormatUnsigned, + eFormatPointer, + eFormatVectorOfChar, + eFormatVectorOfSInt8, + eFormatVectorOfUInt8, + eFormatVectorOfSInt16, + eFormatVectorOfUInt16, + eFormatVectorOfSInt32, + eFormatVectorOfUInt32, + eFormatVectorOfSInt64, + eFormatVectorOfUInt64, + eFormatVectorOfFloat32, + eFormatVectorOfFloat64, + eFormatVectorOfUInt128, + eFormatComplexInteger, // Integer complex type + eFormatCharArray, // Print characters with no single quotes, used for character arrays that can contain non printable characters + eFormatAddressInfo, // Describe what an address points to (func + offset with file/line, symbol + offset, data, etc) + eFormatHexFloat, // ISO C99 hex float string + eFormatInstruction, // Disassemble an opcode + eFormatVoid, // Do not print this + kNumFormats + } Format; + + //---------------------------------------------------------------------- + // Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls + //---------------------------------------------------------------------- + typedef enum DescriptionLevel + { + eDescriptionLevelBrief = 0, + eDescriptionLevelFull, + eDescriptionLevelVerbose, + eDescriptionLevelInitial, + kNumDescriptionLevels + } DescriptionLevel; + + //---------------------------------------------------------------------- + // Script interpreter types + //---------------------------------------------------------------------- + typedef enum ScriptLanguage + { + eScriptLanguageNone, + eScriptLanguagePython, + eScriptLanguageDefault = eScriptLanguagePython + } ScriptLanguage; + + //---------------------------------------------------------------------- + // Register numbering types + //---------------------------------------------------------------------- + typedef enum RegisterKind + { + eRegisterKindGCC = 0, // the register numbers seen in eh_frame + eRegisterKindDWARF, // the register numbers seen DWARF + eRegisterKindGeneric, // insn ptr reg, stack ptr reg, etc not specific to any particular target + eRegisterKindGDB, // the register numbers gdb uses (matches stabs numbers?) + eRegisterKindLLDB, // lldb's internal register numbers + kNumRegisterKinds + } RegisterKind; + + //---------------------------------------------------------------------- + // Thread stop reasons + //---------------------------------------------------------------------- + typedef enum StopReason + { + eStopReasonInvalid = 0, + eStopReasonNone, + eStopReasonTrace, + eStopReasonBreakpoint, + eStopReasonWatchpoint, + eStopReasonSignal, + eStopReasonException, + eStopReasonExec, // Program was re-exec'ed + eStopReasonPlanComplete, + eStopReasonThreadExiting + } StopReason; + + //---------------------------------------------------------------------- + // Command Return Status Types + //---------------------------------------------------------------------- + typedef enum ReturnStatus + { + eReturnStatusInvalid, + eReturnStatusSuccessFinishNoResult, + eReturnStatusSuccessFinishResult, + eReturnStatusSuccessContinuingNoResult, + eReturnStatusSuccessContinuingResult, + eReturnStatusStarted, + eReturnStatusFailed, + eReturnStatusQuit + } ReturnStatus; + + + //---------------------------------------------------------------------- + // Connection Status Types + //---------------------------------------------------------------------- + typedef enum ConnectionStatus + { + eConnectionStatusSuccess, // Success + eConnectionStatusEndOfFile, // End-of-file encountered + eConnectionStatusError, // Check GetError() for details + eConnectionStatusTimedOut, // Request timed out + eConnectionStatusNoConnection, // No connection + eConnectionStatusLostConnection // Lost connection while connected to a valid connection + } ConnectionStatus; + + typedef enum ErrorType + { + eErrorTypeInvalid, + eErrorTypeGeneric, ///< Generic errors that can be any value. + eErrorTypeMachKernel, ///< Mach kernel error codes. + eErrorTypePOSIX ///< POSIX error codes. + } ErrorType; + + + typedef enum ValueType + { + eValueTypeInvalid = 0, + eValueTypeVariableGlobal = 1, // globals variable + eValueTypeVariableStatic = 2, // static variable + eValueTypeVariableArgument = 3, // function argument variables + eValueTypeVariableLocal = 4, // function local variables + eValueTypeRegister = 5, // stack frame register value + eValueTypeRegisterSet = 6, // A collection of stack frame register values + eValueTypeConstResult = 7 // constant result variables + } ValueType; + + //---------------------------------------------------------------------- + // Token size/granularities for Input Readers + //---------------------------------------------------------------------- + + typedef enum InputReaderGranularity + { + eInputReaderGranularityInvalid = 0, + eInputReaderGranularityByte, + eInputReaderGranularityWord, + eInputReaderGranularityLine, + eInputReaderGranularityAll + } InputReaderGranularity; + + //------------------------------------------------------------------ + /// These mask bits allow a common interface for queries that can + /// limit the amount of information that gets parsed to only the + /// information that is requested. These bits also can indicate what + /// actually did get resolved during query function calls. + /// + /// Each definition corresponds to a one of the member variables + /// in this class, and requests that that item be resolved, or + /// indicates that the member did get resolved. + //------------------------------------------------------------------ + typedef enum SymbolContextItem + { + eSymbolContextTarget = (1u << 0), ///< Set when \a target is requested from a query, or was located in query results + eSymbolContextModule = (1u << 1), ///< Set when \a module is requested from a query, or was located in query results + eSymbolContextCompUnit = (1u << 2), ///< Set when \a comp_unit is requested from a query, or was located in query results + eSymbolContextFunction = (1u << 3), ///< Set when \a function is requested from a query, or was located in query results + eSymbolContextBlock = (1u << 4), ///< Set when the deepest \a block is requested from a query, or was located in query results + eSymbolContextLineEntry = (1u << 5), ///< Set when \a line_entry is requested from a query, or was located in query results + eSymbolContextSymbol = (1u << 6), ///< Set when \a symbol is requested from a query, or was located in query results + eSymbolContextEverything = ((eSymbolContextSymbol << 1) - 1u) ///< Indicates to try and lookup everything up during a query. + } SymbolContextItem; + + typedef enum Permissions + { + ePermissionsWritable = (1u << 0), + ePermissionsReadable = (1u << 1), + ePermissionsExecutable = (1u << 2) + } Permissions; + + typedef enum InputReaderAction + { + eInputReaderActivate, // reader is newly pushed onto the reader stack + eInputReaderAsynchronousOutputWritten, // an async output event occurred; the reader may want to do something + eInputReaderReactivate, // reader is on top of the stack again after another reader was popped off + eInputReaderDeactivate, // another reader was pushed on the stack + eInputReaderGotToken, // reader got one of its tokens (granularity) + eInputReaderInterrupt, // reader received an interrupt signal (probably from a control-c) + eInputReaderEndOfFile, // reader received an EOF char (probably from a control-d) + eInputReaderDone // reader was just popped off the stack and is done + } InputReaderAction; + + typedef enum BreakpointEventType + { + eBreakpointEventTypeInvalidType = (1u << 0), + eBreakpointEventTypeAdded = (1u << 1), + eBreakpointEventTypeRemoved = (1u << 2), + eBreakpointEventTypeLocationsAdded = (1u << 3), // Locations added doesn't get sent when the breakpoint is created + eBreakpointEventTypeLocationsRemoved = (1u << 4), + eBreakpointEventTypeLocationsResolved = (1u << 5), + eBreakpointEventTypeEnabled = (1u << 6), + eBreakpointEventTypeDisabled = (1u << 7), + eBreakpointEventTypeCommandChanged = (1u << 8), + eBreakpointEventTypeConditionChanged = (1u << 9), + eBreakpointEventTypeIgnoreChanged = (1u << 10), + eBreakpointEventTypeThreadChanged = (1u << 11) + } BreakpointEventType; + + typedef enum WatchpointEventType + { + eWatchpointEventTypeInvalidType = (1u << 0), + eWatchpointEventTypeAdded = (1u << 1), + eWatchpointEventTypeRemoved = (1u << 2), + eWatchpointEventTypeEnabled = (1u << 6), + eWatchpointEventTypeDisabled = (1u << 7), + eWatchpointEventTypeCommandChanged = (1u << 8), + eWatchpointEventTypeConditionChanged = (1u << 9), + eWatchpointEventTypeIgnoreChanged = (1u << 10), + eWatchpointEventTypeThreadChanged = (1u << 11), + eWatchpointEventTypeTypeChanged = (1u << 12) + } WatchpointEventType; + + + //---------------------------------------------------------------------- + /// Programming language type. + /// + /// These enumerations use the same language enumerations as the DWARF + /// specification for ease of use and consistency. + /// The enum -> string code is in LanguageRuntime.cpp, don't change this + /// table without updating that code as well. + //---------------------------------------------------------------------- + typedef enum LanguageType + { + eLanguageTypeUnknown = 0x0000, ///< Unknown or invalid language value. + eLanguageTypeC89 = 0x0001, ///< ISO C:1989. + eLanguageTypeC = 0x0002, ///< Non-standardized C, such as K&R. + eLanguageTypeAda83 = 0x0003, ///< ISO Ada:1983. + eLanguageTypeC_plus_plus = 0x0004, ///< ISO C++:1998. + eLanguageTypeCobol74 = 0x0005, ///< ISO Cobol:1974. + eLanguageTypeCobol85 = 0x0006, ///< ISO Cobol:1985. + eLanguageTypeFortran77 = 0x0007, ///< ISO Fortran 77. + eLanguageTypeFortran90 = 0x0008, ///< ISO Fortran 90. + eLanguageTypePascal83 = 0x0009, ///< ISO Pascal:1983. + eLanguageTypeModula2 = 0x000a, ///< ISO Modula-2:1996. + eLanguageTypeJava = 0x000b, ///< Java. + eLanguageTypeC99 = 0x000c, ///< ISO C:1999. + eLanguageTypeAda95 = 0x000d, ///< ISO Ada:1995. + eLanguageTypeFortran95 = 0x000e, ///< ISO Fortran 95. + eLanguageTypePLI = 0x000f, ///< ANSI PL/I:1976. + eLanguageTypeObjC = 0x0010, ///< Objective-C. + eLanguageTypeObjC_plus_plus = 0x0011, ///< Objective-C++. + eLanguageTypeUPC = 0x0012, ///< Unified Parallel C. + eLanguageTypeD = 0x0013, ///< D. + eLanguageTypePython = 0x0014, ///< Python. + eNumLanguageTypes + } LanguageType; + + typedef enum DynamicValueType + { + eNoDynamicValues = 0, + eDynamicCanRunTarget = 1, + eDynamicDontRunTarget = 2 + } DynamicValueType; + + typedef enum AccessType + { + eAccessNone, + eAccessPublic, + eAccessPrivate, + eAccessProtected, + eAccessPackage + } AccessType; + + typedef enum CommandArgumentType + { + eArgTypeAddress = 0, + eArgTypeAddressOrExpression, + eArgTypeAliasName, + eArgTypeAliasOptions, + eArgTypeArchitecture, + eArgTypeBoolean, + eArgTypeBreakpointID, + eArgTypeBreakpointIDRange, + eArgTypeByteSize, + eArgTypeClassName, + eArgTypeCommandName, + eArgTypeCount, + eArgTypeDirectoryName, + eArgTypeDisassemblyFlavor, + eArgTypeEndAddress, + eArgTypeExpression, + eArgTypeExpressionPath, + eArgTypeExprFormat, + eArgTypeFilename, + eArgTypeFormat, + eArgTypeFrameIndex, + eArgTypeFullName, + eArgTypeFunctionName, + eArgTypeFunctionOrSymbol, + eArgTypeGDBFormat, + eArgTypeIndex, + eArgTypeLanguage, + eArgTypeLineNum, + eArgTypeLogCategory, + eArgTypeLogChannel, + eArgTypeMethod, + eArgTypeName, + eArgTypeNewPathPrefix, + eArgTypeNumLines, + eArgTypeNumberPerLine, + eArgTypeOffset, + eArgTypeOldPathPrefix, + eArgTypeOneLiner, + eArgTypePid, + eArgTypePlugin, + eArgTypeProcessName, + eArgTypePythonClass, + eArgTypePythonFunction, + eArgTypePythonScript, + eArgTypeQueueName, + eArgTypeRegisterName, + eArgTypeRegularExpression, + eArgTypeRunArgs, + eArgTypeRunMode, + eArgTypeScriptedCommandSynchronicity, + eArgTypeScriptLang, + eArgTypeSearchWord, + eArgTypeSelector, + eArgTypeSettingIndex, + eArgTypeSettingKey, + eArgTypeSettingPrefix, + eArgTypeSettingVariableName, + eArgTypeShlibName, + eArgTypeSourceFile, + eArgTypeSortOrder, + eArgTypeStartAddress, + eArgTypeSummaryString, + eArgTypeSymbol, + eArgTypeThreadID, + eArgTypeThreadIndex, + eArgTypeThreadName, + eArgTypeUnsignedInteger, + eArgTypeUnixSignal, + eArgTypeVarName, + eArgTypeValue, + eArgTypeWidth, + eArgTypeNone, + eArgTypePlatform, + eArgTypeWatchpointID, + eArgTypeWatchpointIDRange, + eArgTypeWatchType, + eArgTypeLastArg // Always keep this entry as the last entry in this enumeration!! + } CommandArgumentType; + + //---------------------------------------------------------------------- + // Symbol types + //---------------------------------------------------------------------- + typedef enum SymbolType + { + eSymbolTypeAny = 0, + eSymbolTypeInvalid = 0, + eSymbolTypeAbsolute, + eSymbolTypeCode, + eSymbolTypeResolver, + eSymbolTypeData, + eSymbolTypeTrampoline, + eSymbolTypeRuntime, + eSymbolTypeException, + eSymbolTypeSourceFile, + eSymbolTypeHeaderFile, + eSymbolTypeObjectFile, + eSymbolTypeCommonBlock, + eSymbolTypeBlock, + eSymbolTypeLocal, + eSymbolTypeParam, + eSymbolTypeVariable, + eSymbolTypeVariableType, + eSymbolTypeLineEntry, + eSymbolTypeLineHeader, + eSymbolTypeScopeBegin, + eSymbolTypeScopeEnd, + eSymbolTypeAdditional, // When symbols take more than one entry, the extra entries get this type + eSymbolTypeCompiler, + eSymbolTypeInstrumentation, + eSymbolTypeUndefined, + eSymbolTypeObjCClass, + eSymbolTypeObjCMetaClass, + eSymbolTypeObjCIVar + } SymbolType; + + typedef enum SectionType + { + eSectionTypeInvalid, + eSectionTypeCode, + eSectionTypeContainer, // The section contains child sections + eSectionTypeData, + eSectionTypeDataCString, // Inlined C string data + eSectionTypeDataCStringPointers, // Pointers to C string data + eSectionTypeDataSymbolAddress, // Address of a symbol in the symbol table + eSectionTypeData4, + eSectionTypeData8, + eSectionTypeData16, + eSectionTypeDataPointers, + eSectionTypeDebug, + eSectionTypeZeroFill, + eSectionTypeDataObjCMessageRefs, // Pointer to function pointer + selector + eSectionTypeDataObjCCFStrings, // Objective C const CFString/NSString objects + eSectionTypeDWARFDebugAbbrev, + eSectionTypeDWARFDebugAranges, + eSectionTypeDWARFDebugFrame, + eSectionTypeDWARFDebugInfo, + eSectionTypeDWARFDebugLine, + eSectionTypeDWARFDebugLoc, + eSectionTypeDWARFDebugMacInfo, + eSectionTypeDWARFDebugPubNames, + eSectionTypeDWARFDebugPubTypes, + eSectionTypeDWARFDebugRanges, + eSectionTypeDWARFDebugStr, + eSectionTypeDWARFAppleNames, + eSectionTypeDWARFAppleTypes, + eSectionTypeDWARFAppleNamespaces, + eSectionTypeDWARFAppleObjC, + eSectionTypeELFSymbolTable, // Elf SHT_SYMTAB section + eSectionTypeELFDynamicSymbols, // Elf SHT_DYNSYM section + eSectionTypeELFRelocationEntries, // Elf SHT_REL or SHT_REL section + eSectionTypeELFDynamicLinkInfo, // Elf SHT_DYNAMIC section + eSectionTypeEHFrame, + eSectionTypeOther + + } SectionType; + + typedef enum EmulateInstructionOptions + { + eEmulateInstructionOptionNone = (0u), + eEmulateInstructionOptionAutoAdvancePC = (1u << 0), + eEmulateInstructionOptionIgnoreConditions = (1u << 1) + } EmulateInstructionOptions; + + typedef enum FunctionNameType + { + eFunctionNameTypeNone = 0u, + eFunctionNameTypeAuto = (1u << 1), // Automatically figure out which FunctionNameType + // bits to set based on the function name. + eFunctionNameTypeFull = (1u << 2), // The function name. + // For C this is the same as just the name of the function + // For C++ this is the mangled or demangled version of the mangled name. + // For ObjC this is the full function signature with the + or + // - and the square brackets and the class and selector + eFunctionNameTypeBase = (1u << 3), // The function name only, no namespaces or arguments and no class + // methods or selectors will be searched. + eFunctionNameTypeMethod = (1u << 4), // Find function by method name (C++) with no namespace or arguments + eFunctionNameTypeSelector = (1u << 5), // Find function by selector name (ObjC) names + eFunctionNameTypeAny = eFunctionNameTypeAuto // DEPRECATED: use eFunctionNameTypeAuto + } FunctionNameType; + + + //---------------------------------------------------------------------- + // Basic types enumeration for the public API SBType::GetBasicType() + //---------------------------------------------------------------------- + typedef enum BasicType + { + eBasicTypeInvalid = 0, + eBasicTypeVoid = 1, + eBasicTypeChar, + eBasicTypeSignedChar, + eBasicTypeUnsignedChar, + eBasicTypeWChar, + eBasicTypeSignedWChar, + eBasicTypeUnsignedWChar, + eBasicTypeChar16, + eBasicTypeChar32, + eBasicTypeShort, + eBasicTypeUnsignedShort, + eBasicTypeInt, + eBasicTypeUnsignedInt, + eBasicTypeLong, + eBasicTypeUnsignedLong, + eBasicTypeLongLong, + eBasicTypeUnsignedLongLong, + eBasicTypeInt128, + eBasicTypeUnsignedInt128, + eBasicTypeBool, + eBasicTypeHalf, + eBasicTypeFloat, + eBasicTypeDouble, + eBasicTypeLongDouble, + eBasicTypeFloatComplex, + eBasicTypeDoubleComplex, + eBasicTypeLongDoubleComplex, + eBasicTypeObjCID, + eBasicTypeObjCClass, + eBasicTypeObjCSel, + eBasicTypeNullPtr, + eBasicTypeOther + } BasicType; + + typedef enum TypeClass + { + eTypeClassInvalid = (0u), + eTypeClassArray = (1u << 0), + eTypeClassBlockPointer = (1u << 1), + eTypeClassBuiltin = (1u << 2), + eTypeClassClass = (1u << 3), + eTypeClassComplexFloat = (1u << 4), + eTypeClassComplexInteger = (1u << 5), + eTypeClassEnumeration = (1u << 6), + eTypeClassFunction = (1u << 7), + eTypeClassMemberPointer = (1u << 8), + eTypeClassObjCObject = (1u << 9), + eTypeClassObjCInterface = (1u << 10), + eTypeClassObjCObjectPointer = (1u << 11), + eTypeClassPointer = (1u << 12), + eTypeClassReference = (1u << 13), + eTypeClassStruct = (1u << 14), + eTypeClassTypedef = (1u << 15), + eTypeClassUnion = (1u << 16), + eTypeClassVector = (1u << 17), + // Define the last type class as the MSBit of a 32 bit value + eTypeClassOther = (1u << 31), + // Define a mask that can be used for any type when finding types + eTypeClassAny = (0xffffffffu) + } TypeClass; + + typedef enum TemplateArgumentKind + { + eTemplateArgumentKindNull = 0, + eTemplateArgumentKindType, + eTemplateArgumentKindDeclaration, + eTemplateArgumentKindIntegral, + eTemplateArgumentKindTemplate, + eTemplateArgumentKindTemplateExpansion, + eTemplateArgumentKindExpression, + eTemplateArgumentKindPack + + } TemplateArgumentKind; + + //---------------------------------------------------------------------- + // Options that can be set for a formatter to alter its behavior + // Not all of these are applicable to all formatter types + //---------------------------------------------------------------------- + typedef enum TypeOptions + { + eTypeOptionNone = (0u), + eTypeOptionCascade = (1u << 0), + eTypeOptionSkipPointers = (1u << 1), + eTypeOptionSkipReferences = (1u << 2), + eTypeOptionHideChildren = (1u << 3), + eTypeOptionHideValue = (1u << 4), + eTypeOptionShowOneLiner = (1u << 5), + eTypeOptionHideNames = (1u << 6) + } TypeOptions; + + //---------------------------------------------------------------------- + // This is the return value for frame comparisons. When frame A pushes + // frame B onto the stack, frame A is OLDER than frame B. + //---------------------------------------------------------------------- + typedef enum FrameComparison + { + eFrameCompareInvalid, + eFrameCompareUnknown, + eFrameCompareEqual, + eFrameCompareYounger, + eFrameCompareOlder + } FrameComparison; + + //---------------------------------------------------------------------- + // Address Class + // + // A way of classifying an address used for disassembling and setting + // breakpoints. Many object files can track exactly what parts of their + // object files are code, data and other information. This is of course + // above and beyond just looking at the section types. For example, code + // might contain PC relative data and the object file might be able to + // tell us that an address in code is data. + //---------------------------------------------------------------------- + typedef enum AddressClass + { + eAddressClassInvalid, + eAddressClassUnknown, + eAddressClassCode, + eAddressClassCodeAlternateISA, + eAddressClassData, + eAddressClassDebug, + eAddressClassRuntime + } AddressClass; + +} // namespace lldb + + +#endif // LLDB_lldb_enumerations_h_ diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h new file mode 100644 index 0000000..84af8b6 --- /dev/null +++ b/include/lldb/lldb-forward.h @@ -0,0 +1,378 @@ +//===-- lldb-forward.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_lldb_forward_h_ +#define LLDB_lldb_forward_h_ + +#if defined(__cplusplus) + +#include "lldb/Utility/SharingPtr.h" + +//---------------------------------------------------------------------- +// lldb forward declarations +//---------------------------------------------------------------------- +namespace lldb_private { + +class ABI; +class Address; +class AddressImpl; +class AddressRange; +class AddressResolver; +class ArchSpec; +class Args; +class ASTResultSynthesizer; +class Baton; +class Block; +class Breakpoint; +class BreakpointID; +class BreakpointIDList; +class BreakpointList; +class BreakpointLocation; +class BreakpointLocationCollection; +class BreakpointLocationList; +class BreakpointOptions; +class BreakpointResolver; +class BreakpointSite; +class BreakpointSiteList; +class BroadcastEventSpec; +class Broadcaster; +class BroadcasterManager; +class CPPLanguageRuntime; +class ClangASTContext; +class ClangASTImporter; +class ClangASTMetadata; +class ClangASTSource; +class ClangASTType; +class ClangNamespaceDecl; +class ClangExpression; +class ClangExpressionDeclMap; +class ClangExpressionParser; +class ClangExpressionVariable; +class ClangExpressionVariableList; +class ClangExpressionVariableList; +class ClangExpressionVariables; +class ClangFunction; +class ClangPersistentVariables; +class ClangUserExpression; +class ClangUtilityFunction; +class CommandInterpreter; +class CommandObject; +class CommandReturnObject; +class Communication; +class CompileUnit; +class Condition; +class Connection; +class ConnectionFileDescriptor; +class ConstString; +class CXXSyntheticChildren; +class DWARFCallFrameInfo; +class DWARFExpression; +class DataBuffer; +class DataEncoder; +class DataExtractor; +class Debugger; +class Declaration; +class Disassembler; +class DynamicLibrary; +class DynamicLoader; +class EmulateInstruction; +class Error; +class EvaluateExpressionOptions; +class Event; +class EventData; +class ExecutionContext; +class ExecutionContextRef; +class ExecutionContextRefLocker; +class ExecutionContextScope; +class FileSpec; +class FileSpecList; +class Flags; +class TypeCategoryImpl; +class FormatManager; +class FuncUnwinders; +class Function; +class FunctionInfo; +class InlineFunctionInfo; +class InputReader; +class Instruction; +class InstructionList; +class IRExecutionUnit; +class LanguageRuntime; +class LineTable; +class Listener; +class Log; +class LogChannel; +class Mangled; +class Materializer; +class Module; +class ModuleList; +class ModuleSpec; +class ModuleSpecList; +class Mutex; +struct NameSearchContext; +class ObjCLanguageRuntime; +class ObjectContainer; +class OptionGroup; +class OptionGroupPlatform; +class ObjectFile; +class OperatingSystem; +class Options; +class OptionValue; +class OptionValueArch; +class OptionValueArgs; +class OptionValueArray; +class OptionValueBoolean; +class OptionValueDictionary; +class OptionValueEnumeration; +class OptionValueFileSpec; +class OptionValueFileSpecList; +class OptionValueFormat; +class OptionValuePathMappings; +class OptionValueProperties; +class OptionValueRegex; +class OptionValueSInt64; +class OptionValueString; +class OptionValueUInt64; +class OptionValueUUID; +class NamedOption; +class PathMappingList; +class Platform; +class Process; +class ProcessAttachInfo; +class ProcessModID; +class ProcessInfo; +class ProcessInstanceInfo; +class ProcessInstanceInfoList; +class ProcessInstanceInfoMatch; +class ProcessLaunchInfo; +class Property; +struct PropertyDefinition; +class PythonArray; +class PythonDictionary; +class PythonInteger; +class PythonObject; +class PythonString; +class RegisterContext; +class RegisterLocation; +class RegisterLocationList; +class RegisterValue; +class RegularExpression; +class Scalar; +class ScriptInterpreter; +class ScriptInterpreterLocker; +class ScriptInterpreterObject; +#ifndef LLDB_DISABLE_PYTHON +class ScriptInterpreterPython; +struct ScriptSummaryFormat; +#endif +class SearchFilter; +class Section; +class SectionImpl; +class SectionList; +class Settings; +class SourceManager; +class SourceManagerImpl; +class StackFrame; +class StackFrameImpl; +class StackFrameList; +class StackID; +class StopInfo; +class Stoppoint; +class StoppointCallbackContext; +class StoppointLocation; +class Stream; +template <unsigned N> class StreamBuffer; +class StreamFile; +class StreamString; +class StringList; +struct StringSummaryFormat; +class TypeSummaryImpl; +class Symbol; +class SymbolContext; +class SymbolContextList; +class SymbolContextScope; +class SymbolContextSpecifier; +class SymbolFile; +class SymbolFileType; +class SymbolVendor; +class Symtab; +class SyntheticChildren; +class SyntheticChildrenFrontEnd; +class TypeFilterImpl; +#ifndef LLDB_DISABLE_PYTHON +class ScriptedSyntheticChildren; +#endif +class Target; +class TargetList; +class Thread; +class ThreadList; +class ThreadPlan; +class ThreadPlanBase; +class ThreadPlanRunToAddress; +class ThreadPlanStepInstruction; +class ThreadPlanStepOut; +class ThreadPlanStepOverBreakpoint; +class ThreadPlanStepRange; +class ThreadPlanStepThrough; +class ThreadPlanTracer; +class ThreadSpec; +class TimeValue; +class Type; +class TypeCategoryMap; +class TypeImpl; +class TypeAndOrName; +class TypeList; +class TypeListImpl; +class TypeMemberImpl; +class TypeNameSpecifierImpl; +class UUID; +class Unwind; +class UnwindAssembly; +class UnwindPlan; +class UnwindTable; +class VMRange; +class Value; +class TypeFormatImpl; +class ValueList; +class ValueObject; +class ValueObjectChild; +class ValueObjectConstResult; +class ValueObjectConstResultChild; +class ValueObjectConstResultImpl; +class ValueObjectList; +class Variable; +class VariableList; +class Watchpoint; +class WatchpointList; +class WatchpointOptions; +struct LineEntry; + +} // namespace lldb_private + +//---------------------------------------------------------------------- +// lldb forward declarations +//---------------------------------------------------------------------- +namespace lldb { + + typedef std::shared_ptr<lldb_private::ABI> ABISP; + typedef std::shared_ptr<lldb_private::Baton> BatonSP; + typedef std::shared_ptr<lldb_private::Block> BlockSP; + typedef std::shared_ptr<lldb_private::Breakpoint> BreakpointSP; + typedef std::weak_ptr<lldb_private::Breakpoint> BreakpointWP; + typedef std::shared_ptr<lldb_private::BreakpointSite> BreakpointSiteSP; + typedef std::weak_ptr<lldb_private::BreakpointSite> BreakpointSiteWP; + typedef std::shared_ptr<lldb_private::BreakpointLocation> BreakpointLocationSP; + typedef std::weak_ptr<lldb_private::BreakpointLocation> BreakpointLocationWP; + typedef std::shared_ptr<lldb_private::BreakpointResolver> BreakpointResolverSP; + typedef std::shared_ptr<lldb_private::Broadcaster> BroadcasterSP; + typedef std::shared_ptr<lldb_private::ClangExpressionVariable> ClangExpressionVariableSP; + typedef std::shared_ptr<lldb_private::CommandObject> CommandObjectSP; + typedef std::shared_ptr<lldb_private::Communication> CommunicationSP; + typedef std::shared_ptr<lldb_private::Connection> ConnectionSP; + typedef std::shared_ptr<lldb_private::CompileUnit> CompUnitSP; + typedef std::shared_ptr<lldb_private::DataBuffer> DataBufferSP; + typedef std::shared_ptr<lldb_private::DataExtractor> DataExtractorSP; + typedef std::shared_ptr<lldb_private::Debugger> DebuggerSP; + typedef std::weak_ptr<lldb_private::Debugger> DebuggerWP; + typedef std::shared_ptr<lldb_private::Disassembler> DisassemblerSP; + typedef std::shared_ptr<lldb_private::DynamicLibrary> DynamicLibrarySP; + typedef std::shared_ptr<lldb_private::DynamicLoader> DynamicLoaderSP; + typedef std::shared_ptr<lldb_private::Event> EventSP; + typedef std::shared_ptr<lldb_private::ExecutionContextRef> ExecutionContextRefSP; + typedef std::shared_ptr<lldb_private::Function> FunctionSP; + typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP; + typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP; + typedef std::shared_ptr<lldb_private::InputReader> InputReaderSP; + typedef std::shared_ptr<lldb_private::Instruction> InstructionSP; + typedef std::shared_ptr<lldb_private::LanguageRuntime> LanguageRuntimeSP; + typedef std::shared_ptr<lldb_private::LineTable> LineTableSP; + typedef std::shared_ptr<lldb_private::Listener> ListenerSP; + typedef std::shared_ptr<lldb_private::LogChannel> LogChannelSP; + typedef std::shared_ptr<lldb_private::Module> ModuleSP; + typedef std::weak_ptr<lldb_private::Module> ModuleWP; + typedef std::shared_ptr<lldb_private::ObjectFile> ObjectFileSP; + typedef std::weak_ptr<lldb_private::ObjectFile> ObjectFileWP; + typedef std::shared_ptr<lldb_private::OptionValue> OptionValueSP; + typedef std::weak_ptr<lldb_private::OptionValue> OptionValueWP; + typedef std::shared_ptr<lldb_private::OptionValueArch> OptionValueArchSP; + typedef std::shared_ptr<lldb_private::OptionValueArgs> OptionValueArgsSP; + typedef std::shared_ptr<lldb_private::OptionValueArray> OptionValueArraySP; + typedef std::shared_ptr<lldb_private::OptionValueBoolean> OptionValueBooleanSP; + typedef std::shared_ptr<lldb_private::OptionValueDictionary> OptionValueDictionarySP; + typedef std::shared_ptr<lldb_private::OptionValueFileSpec> OptionValueFileSpecSP; + typedef std::shared_ptr<lldb_private::OptionValueFileSpecList> OptionValueFileSpecListSP; + typedef std::shared_ptr<lldb_private::OptionValueFormat> OptionValueFormatSP; + typedef std::shared_ptr<lldb_private::OptionValuePathMappings> OptionValuePathMappingsSP; + typedef std::shared_ptr<lldb_private::OptionValueProperties> OptionValuePropertiesSP; + typedef std::shared_ptr<lldb_private::OptionValueRegex> OptionValueRegexSP; + typedef std::shared_ptr<lldb_private::OptionValueSInt64> OptionValueSInt64SP; + typedef std::shared_ptr<lldb_private::OptionValueString> OptionValueStringSP; + typedef std::shared_ptr<lldb_private::OptionValueUInt64> OptionValueUInt64SP; + typedef std::shared_ptr<lldb_private::OptionValueUUID> OptionValueUUIDSP; + typedef std::shared_ptr<lldb_private::Platform> PlatformSP; + typedef std::shared_ptr<lldb_private::Process> ProcessSP; + typedef std::shared_ptr<lldb_private::ProcessAttachInfo> ProcessAttachInfoSP; + typedef std::shared_ptr<lldb_private::ProcessLaunchInfo> ProcessLaunchInfoSP; + typedef std::weak_ptr<lldb_private::Process> ProcessWP; + typedef std::shared_ptr<lldb_private::Property> PropertySP; + typedef std::shared_ptr<lldb_private::RegisterContext> RegisterContextSP; + typedef std::shared_ptr<lldb_private::RegularExpression> RegularExpressionSP; + typedef std::shared_ptr<lldb_private::ScriptInterpreterObject> ScriptInterpreterObjectSP; +#ifndef LLDB_DISABLE_PYTHON + typedef std::shared_ptr<lldb_private::ScriptSummaryFormat> ScriptSummaryFormatSP; +#endif // #ifndef LLDB_DISABLE_PYTHON + typedef std::shared_ptr<lldb_private::Section> SectionSP; + typedef std::weak_ptr<lldb_private::Section> SectionWP; + typedef std::shared_ptr<lldb_private::SearchFilter> SearchFilterSP; + typedef std::shared_ptr<lldb_private::Settings> SettingsSP; + typedef std::shared_ptr<lldb_private::StackFrame> StackFrameSP; + typedef std::weak_ptr<lldb_private::StackFrame> StackFrameWP; + typedef std::shared_ptr<lldb_private::StackFrameList> StackFrameListSP; + typedef std::shared_ptr<lldb_private::StopInfo> StopInfoSP; + typedef std::shared_ptr<lldb_private::StoppointLocation> StoppointLocationSP; + typedef std::shared_ptr<lldb_private::Stream> StreamSP; + typedef std::weak_ptr<lldb_private::Stream> StreamWP; + typedef std::shared_ptr<lldb_private::StringSummaryFormat> StringTypeSummaryImplSP; + typedef std::shared_ptr<lldb_private::SymbolFile> SymbolFileSP; + typedef std::shared_ptr<lldb_private::SymbolFileType> SymbolFileTypeSP; + typedef std::weak_ptr<lldb_private::SymbolFileType> SymbolFileTypeWP; + typedef std::shared_ptr<lldb_private::SymbolContextSpecifier> SymbolContextSpecifierSP; + typedef std::shared_ptr<lldb_private::SyntheticChildren> SyntheticChildrenSP; + typedef std::shared_ptr<lldb_private::SyntheticChildrenFrontEnd> SyntheticChildrenFrontEndSP; + typedef std::shared_ptr<lldb_private::Target> TargetSP; + typedef std::weak_ptr<lldb_private::Target> TargetWP; + typedef std::shared_ptr<lldb_private::Thread> ThreadSP; + typedef std::weak_ptr<lldb_private::Thread> ThreadWP; + typedef std::shared_ptr<lldb_private::ThreadPlan> ThreadPlanSP; + typedef std::shared_ptr<lldb_private::ThreadPlanTracer> ThreadPlanTracerSP; + typedef std::shared_ptr<lldb_private::Type> TypeSP; + typedef std::weak_ptr<lldb_private::Type> TypeWP; + typedef std::shared_ptr<lldb_private::TypeCategoryImpl> TypeCategoryImplSP; + typedef std::shared_ptr<lldb_private::TypeImpl> TypeImplSP; + typedef std::shared_ptr<lldb_private::TypeFilterImpl> TypeFilterImplSP; + typedef std::shared_ptr<lldb_private::TypeFormatImpl> TypeFormatImplSP; + typedef std::shared_ptr<lldb_private::TypeNameSpecifierImpl> TypeNameSpecifierImplSP; + typedef std::shared_ptr<lldb_private::TypeSummaryImpl> TypeSummaryImplSP; +#ifndef LLDB_DISABLE_PYTHON + typedef std::shared_ptr<lldb_private::ScriptedSyntheticChildren> ScriptedSyntheticChildrenSP; +#endif + typedef std::shared_ptr<lldb_private::UnwindPlan> UnwindPlanSP; + typedef lldb_private::SharingPtr<lldb_private::ValueObject> ValueObjectSP; + typedef std::shared_ptr<lldb_private::Value> ValueSP; + typedef std::shared_ptr<lldb_private::ValueList> ValueListSP; + typedef std::shared_ptr<lldb_private::Variable> VariableSP; + typedef std::shared_ptr<lldb_private::VariableList> VariableListSP; + typedef std::shared_ptr<lldb_private::ValueObjectList> ValueObjectListSP; + typedef std::shared_ptr<lldb_private::Watchpoint> WatchpointSP; + +} // namespace lldb + + +#endif // #if defined(__cplusplus) +#endif // LLDB_lldb_forward_h_ diff --git a/include/lldb/lldb-private-enumerations.h b/include/lldb/lldb-private-enumerations.h new file mode 100644 index 0000000..60c9090 --- /dev/null +++ b/include/lldb/lldb-private-enumerations.h @@ -0,0 +1,245 @@ +//===-- lldb-private-enumerations.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_lldb_private_enumerations_h_ +#define LLDB_lldb_private_enumerations_h_ + +namespace lldb_private { + +//---------------------------------------------------------------------- +// Thread Step Types +//---------------------------------------------------------------------- +typedef enum StepType +{ + eStepTypeNone, + eStepTypeTrace, ///< Single step one instruction. + eStepTypeTraceOver, ///< Single step one instruction, stepping over. + eStepTypeInto, ///< Single step into a specified context. + eStepTypeOver, ///< Single step over a specified context. + eStepTypeOut ///< Single step out a specified context. +} StepType; + +//---------------------------------------------------------------------- +// Address Types +//---------------------------------------------------------------------- +typedef enum AddressType +{ + eAddressTypeInvalid = 0, + eAddressTypeFile, ///< Address is an address as found in an object or symbol file + eAddressTypeLoad, ///< Address is an address as in the current target inferior process + eAddressTypeHost ///< Address is an address in the process that is running this code +} AddressType; + +//---------------------------------------------------------------------- +// Votes - Need a tri-state, yes, no, no opinion... +//---------------------------------------------------------------------- +typedef enum Vote +{ + eVoteNo = -1, + eVoteNoOpinion = 0, + eVoteYes = 1 +} Vote; + +typedef enum ArchitectureType +{ + eArchTypeInvalid, + eArchTypeMachO, + eArchTypeELF, + kNumArchTypes +} ArchitectureType; + +//---------------------------------------------------------------------- +/// Settable state variable types. +/// +//---------------------------------------------------------------------- + +//typedef enum SettableVariableType +//{ +// eSetVarTypeInt, +// eSetVarTypeBoolean, +// eSetVarTypeString, +// eSetVarTypeArray, +// eSetVarTypeDictionary, +// eSetVarTypeEnum, +// eSetVarTypeNone +//} SettableVariableType; + +typedef enum VarSetOperationType +{ + eVarSetOperationReplace, + eVarSetOperationInsertBefore, + eVarSetOperationInsertAfter, + eVarSetOperationRemove, + eVarSetOperationAppend, + eVarSetOperationClear, + eVarSetOperationAssign, + eVarSetOperationInvalid +} VarSetOperationType; + +typedef enum ArgumentRepetitionType +{ + eArgRepeatPlain, // Exactly one occurrence + eArgRepeatOptional, // At most one occurrence, but it's optional + eArgRepeatPlus, // One or more occurrences + eArgRepeatStar, // Zero or more occurrences + eArgRepeatRange, // Repetition of same argument, from 1 to n + eArgRepeatPairPlain, // A pair of arguments that must always go together ([arg-type arg-value]), occurs exactly once + eArgRepeatPairOptional, // A pair that occurs at most once (optional) + eArgRepeatPairPlus, // One or more occurrences of a pair + eArgRepeatPairStar, // Zero or more occurrences of a pair + eArgRepeatPairRange, // A pair that repeats from 1 to n + eArgRepeatPairRangeOptional // A pair that repeats from 1 to n, but is optional +} ArgumentRepetitionType; + +typedef enum SortOrder +{ + eSortOrderNone, + eSortOrderByAddress, + eSortOrderByName +} SortOrder; + + +//---------------------------------------------------------------------- +// Used in conjunction with Host::GetLLDBPath () to find files that +// are related to +//---------------------------------------------------------------------- +typedef enum PathType +{ + ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists + ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) + ePathTypeHeaderDir, // Find LLDB header file directory + ePathTypePythonDir, // Find Python modules (PYTHONPATH) directory + ePathTypeLLDBSystemPlugins, // System plug-ins directory + ePathTypeLLDBUserPlugins // User plug-ins directory +} PathType; + + +//---------------------------------------------------------------------- +// We can execute ThreadPlans on one thread with various fall-back modes +// (try other threads after timeout, etc.) This enum gives the result of +// thread plan executions. +//---------------------------------------------------------------------- +typedef enum ExecutionResults +{ + eExecutionSetupError, + eExecutionCompleted, + eExecutionDiscarded, + eExecutionInterrupted, + eExecutionHitBreakpoint, + eExecutionTimedOut +} ExecutionResults; + +typedef enum ObjCRuntimeVersions { + eObjC_VersionUnknown = 0, + eAppleObjC_V1 = 1, + eAppleObjC_V2 = 2 +} ObjCRuntimeVersions; + + +//---------------------------------------------------------------------- +// LazyBool is for boolean values that need to be calculated lazily. +// Values start off set to eLazyBoolCalculate, and then they can be +// calculated once and set to eLazyBoolNo or eLazyBoolYes. +//---------------------------------------------------------------------- +typedef enum LazyBool { + eLazyBoolCalculate = -1, + eLazyBoolNo = 0, + eLazyBoolYes = 1 +} LazyBool; + +//------------------------------------------------------------------ +/// Name matching +//------------------------------------------------------------------ +typedef enum NameMatchType +{ + eNameMatchIgnore, + eNameMatchEquals, + eNameMatchContains, + eNameMatchStartsWith, + eNameMatchEndsWith, + eNameMatchRegularExpression + +} NameMatchType; + + +//------------------------------------------------------------------ +/// Instruction types +//------------------------------------------------------------------ +typedef enum InstructionType +{ + eInstructionTypeAny, // Support for any instructions at all (at least one) + eInstructionTypePrologueEpilogue, // All prologue and epilogue instructons that push and pop register values and modify sp/fp + eInstructionTypePCModifying, // Any instruction that modifies the program counter/instruction pointer + eInstructionTypeAll // All instructions of any kind + +} InstructionType; + + +//------------------------------------------------------------------ +/// Format category entry types +//------------------------------------------------------------------ +typedef enum FormatCategoryItem +{ + eFormatCategoryItemSummary = 0x0001, + eFormatCategoryItemRegexSummary = 0x0002, + eFormatCategoryItemFilter = 0x0004, + eFormatCategoryItemRegexFilter = 0x0008, + eFormatCategoryItemSynth = 0x0010, + eFormatCategoryItemRegexSynth = 0x0020 +} FormatCategoryItem; + +//------------------------------------------------------------------ +/// Expression execution policies +//------------------------------------------------------------------ +typedef enum { + eExecutionPolicyOnlyWhenNeeded, + eExecutionPolicyNever, + eExecutionPolicyAlways +} ExecutionPolicy; + +//---------------------------------------------------------------------- +// Ways that the FormatManager picks a particular format for a type +//---------------------------------------------------------------------- +typedef enum FormatterChoiceCriterion +{ + eFormatterChoiceCriterionDirectChoice = 0x00000000, + eFormatterChoiceCriterionStrippedPointerReference = 0x00000001, + eFormatterChoiceCriterionNavigatedTypedefs = 0x00000002, + eFormatterChoiceCriterionRegularExpressionSummary = 0x00000004, + eFormatterChoiceCriterionRegularExpressionFilter = 0x00000004, + eFormatterChoiceCriterionDynamicObjCDiscovery = 0x00000008, + eFormatterChoiceCriterionStrippedBitField = 0x00000010, + eFormatterChoiceCriterionWentToStaticValue = 0x00000020 +} FormatterChoiceCriterion; + +//---------------------------------------------------------------------- +// Synchronicity behavior of scripted commands +//---------------------------------------------------------------------- +typedef enum ScriptedCommandSynchronicity +{ + eScriptedCommandSynchronicitySynchronous, + eScriptedCommandSynchronicityAsynchronous, + eScriptedCommandSynchronicityCurrentValue // use whatever the current synchronicity is +} ScriptedCommandSynchronicity; + + +//---------------------------------------------------------------------- +// Loading modules from memory +//---------------------------------------------------------------------- +typedef enum MemoryModuleLoadLevel { + eMemoryModuleLoadLevelMinimal, // Load sections only + eMemoryModuleLoadLevelPartial, // Load function bounds but no symbols + eMemoryModuleLoadLevelComplete, // Load sections and all symbols +} MemoryModuleLoadLevel; + + +} // namespace lldb_private + + +#endif // LLDB_lldb_private_enumerations_h_ diff --git a/include/lldb/lldb-private-interfaces.h b/include/lldb/lldb-private-interfaces.h new file mode 100644 index 0000000..949cafe --- /dev/null +++ b/include/lldb/lldb-private-interfaces.h @@ -0,0 +1,46 @@ +//===-- lldb-private-interfaces.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_lldb_private_interfaces_h_ +#define liblldb_lldb_private_interfaces_h_ + +#if defined(__cplusplus) + +#include "lldb/lldb-private.h" + +namespace lldb_private +{ + typedef lldb::ABISP (*ABICreateInstance) (const ArchSpec &arch); + typedef Disassembler* (*DisassemblerCreateInstance) (const ArchSpec &arch, const char *flavor); + typedef DynamicLoader* (*DynamicLoaderCreateInstance) (Process* process, bool force); + typedef ObjectContainer* (*ObjectContainerCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t offset, lldb::offset_t length); + typedef size_t (*ObjectFileGetModuleSpecifications) (const FileSpec &file, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, ModuleSpecList &module_specs); + typedef ObjectFile* (*ObjectFileCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec* file, lldb::offset_t file_offset, lldb::offset_t length); + typedef ObjectFile* (*ObjectFileCreateMemoryInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t offset); + typedef LogChannel* (*LogChannelCreateInstance) (); + typedef EmulateInstruction * (*EmulateInstructionCreateInstance) (const ArchSpec &arch, InstructionType inst_type); + typedef OperatingSystem* (*OperatingSystemCreateInstance) (Process *process, bool force); + typedef LanguageRuntime *(*LanguageRuntimeCreateInstance) (Process *process, lldb::LanguageType language); + typedef Platform* (*PlatformCreateInstance) (bool force, const ArchSpec *arch); + typedef lldb::ProcessSP (*ProcessCreateInstance) (Target &target, Listener &listener, const FileSpec *crash_file_path); + typedef SymbolFile* (*SymbolFileCreateInstance) (ObjectFile* obj_file); + typedef SymbolVendor* (*SymbolVendorCreateInstance) (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); // Module can be NULL for default system symbol vendor + typedef bool (*BreakpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + typedef bool (*WatchpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id); + typedef lldb::ThreadPlanSP (*ThreadPlanShouldStopHereCallback) (ThreadPlan *current_plan, Flags &flags, void *baton); + typedef UnwindAssembly* (*UnwindAssemblyCreateInstance) (const ArchSpec &arch); + typedef int (*ComparisonFunction)(const void *, const void *); + typedef bool (*CommandOverrideCallback)(void *baton, const char **argv); + typedef void (*DebuggerInitializeCallback)(Debugger &debugger); + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) + +#endif // liblldb_lldb_private_interfaces_h_ diff --git a/include/lldb/lldb-private-log.h b/include/lldb/lldb-private-log.h new file mode 100644 index 0000000..31a1c23 --- /dev/null +++ b/include/lldb/lldb-private-log.h @@ -0,0 +1,90 @@ +//===-- lldb-private-log.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_lldb_private_log_h_ +#define liblldb_lldb_private_log_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +//---------------------------------------------------------------------- +// Log Bits specific to logging in lldb +//---------------------------------------------------------------------- +#define LIBLLDB_LOG_VERBOSE (1u << 0) +#define LIBLLDB_LOG_PROCESS (1u << 1) +#define LIBLLDB_LOG_THREAD (1u << 2) +#define LIBLLDB_LOG_DYNAMIC_LOADER (1u << 3) +#define LIBLLDB_LOG_EVENTS (1u << 4) +#define LIBLLDB_LOG_BREAKPOINTS (1u << 5) +#define LIBLLDB_LOG_WATCHPOINTS (1u << 6) +#define LIBLLDB_LOG_STEP (1u << 7) +#define LIBLLDB_LOG_EXPRESSIONS (1u << 8) +#define LIBLLDB_LOG_TEMPORARY (1u << 9) +#define LIBLLDB_LOG_STATE (1u << 10) +#define LIBLLDB_LOG_OBJECT (1u << 11) +#define LIBLLDB_LOG_COMMUNICATION (1u << 12) +#define LIBLLDB_LOG_CONNECTION (1u << 13) +#define LIBLLDB_LOG_HOST (1u << 14) +#define LIBLLDB_LOG_UNWIND (1u << 15) +#define LIBLLDB_LOG_API (1u << 16) +#define LIBLLDB_LOG_SCRIPT (1u << 17) +#define LIBLLDB_LOG_COMMANDS (1U << 18) +#define LIBLLDB_LOG_TYPES (1u << 19) +#define LIBLLDB_LOG_SYMBOLS (1u << 20) +#define LIBLLDB_LOG_MODULES (1u << 21) +#define LIBLLDB_LOG_TARGET (1u << 22) +#define LIBLLDB_LOG_MMAP (1u << 23) +#define LIBLLDB_LOG_OS (1u << 24) +#define LIBLLDB_LOG_ALL (UINT32_MAX) +#define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\ + LIBLLDB_LOG_THREAD |\ + LIBLLDB_LOG_DYNAMIC_LOADER |\ + LIBLLDB_LOG_BREAKPOINTS |\ + LIBLLDB_LOG_WATCHPOINTS |\ + LIBLLDB_LOG_STEP |\ + LIBLLDB_LOG_STATE |\ + LIBLLDB_LOG_SYMBOLS |\ + LIBLLDB_LOG_TARGET |\ + LIBLLDB_LOG_COMMANDS) + +namespace lldb_private { + +void +LogIfAllCategoriesSet (uint32_t mask, const char *format, ...); + +void +LogIfAnyCategoriesSet (uint32_t mask, const char *format, ...); + +Log * +GetLogIfAllCategoriesSet (uint32_t mask); + +Log * +GetLogIfAnyCategoriesSet (uint32_t mask); + +uint32_t +GetLogMask (); + +bool +IsLogVerbose (); + +void +DisableLog (const char **categories, Stream *feedback_strm); + +Log * +EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm); + +void +ListLogCategories (Stream *strm); + +} // namespace lldb_private + +#endif // liblldb_lldb_private_log_h_ diff --git a/include/lldb/lldb-private-types.h b/include/lldb/lldb-private-types.h new file mode 100644 index 0000000..4340af1 --- /dev/null +++ b/include/lldb/lldb-private-types.h @@ -0,0 +1,74 @@ +//===-- lldb-private-types.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_lldb_private_types_h_ +#define liblldb_lldb_private_types_h_ + +#if defined(__cplusplus) + +#include "lldb/lldb-private.h" + +namespace lldb_private +{ + //---------------------------------------------------------------------- + // Every register is described in detail including its name, alternate + // name (optional), encoding, size in bytes and the default display + // format. + //---------------------------------------------------------------------- + typedef struct + { + const char *name; // Name of this register, can't be NULL + const char *alt_name; // Alternate name of this register, can be NULL + uint32_t byte_size; // Size in bytes of the register + uint32_t byte_offset; // The byte offset in the register context data where this register's value is found + lldb::Encoding encoding; // Encoding of the register bits + lldb::Format format; // Default display format + uint32_t kinds[lldb::kNumRegisterKinds]; // Holds all of the various register numbers for all register kinds + uint32_t *value_regs; // List of registers that must be terminated with LLDB_INVALID_REGNUM + uint32_t *invalidate_regs; // List of registers that must be invalidated when this register is modified, list must be terminated with LLDB_INVALID_REGNUM + } RegisterInfo; + + //---------------------------------------------------------------------- + // Registers are grouped into register sets + //---------------------------------------------------------------------- + typedef struct + { + const char *name; // Name of this register set + const char *short_name; // A short name for this register set + size_t num_registers; // The number of registers in REGISTERS array below + const uint32_t *registers; // An array of register numbers in this set + } RegisterSet; + + typedef struct + { + int64_t value; + const char *string_value; + const char *usage; + } OptionEnumValueElement; + + typedef struct + { + uint32_t usage_mask; // Used to mark options that can be used together. If (1 << n & usage_mask) != 0 + // then this option belongs to option set n. + bool required; // This option is required (in the current usage level) + const char *long_option; // Full name for this option. + int short_option; // Single character for this option. + int option_has_arg; // no_argument, required_argument or optional_argument + OptionEnumValueElement *enum_values; // If non-NULL an array of enum values. + uint32_t completion_type; // Cookie the option class can use to do define the argument completion. + lldb::CommandArgumentType argument_type; // Type of argument this option takes + const char *usage_text; // Full text explaining what this options does and what (if any) argument to + // pass it. + } OptionDefinition; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) + +#endif // liblldb_lldb_private_types_h_ diff --git a/include/lldb/lldb-private.h b/include/lldb/lldb-private.h new file mode 100644 index 0000000..9059060 --- /dev/null +++ b/include/lldb/lldb-private.h @@ -0,0 +1,84 @@ +//===-- lldb-private.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_lldb_private_h_ +#define lldb_lldb_private_h_ + +#if defined(__cplusplus) + +#include "lldb/lldb-public.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-private-interfaces.h" +#include "lldb/lldb-private-log.h" +#include "lldb/lldb-private-types.h" + +namespace lldb_private { + +//------------------------------------------------------------------ +/// Initializes lldb. +/// +/// This function should be called prior to using any lldb +/// classes to ensure they have a chance to do any static +/// initialization that they need to do. +//------------------------------------------------------------------ +void +Initialize(); + + +//------------------------------------------------------------------ +/// Notifies any classes that lldb will be terminating soon. +/// +/// This function will be called when the Debugger shared instance +/// is being destructed and will give classes the ability to clean +/// up any threads or other resources they have that they might not +/// be able to clean up in their own destructors. +/// +/// Internal classes that need this ability will need to add their +/// void T::WillTerminate() method in the body of this function in +/// lldb.cpp to ensure it will get called. +/// +/// TODO: when we start having external plug-ins, we will need a way +/// for plug-ins to register a WillTerminate callback. +//------------------------------------------------------------------ +void +WillTerminate(); + +//------------------------------------------------------------------ +/// Terminates lldb +/// +/// This function optionally can be called when clients are done +/// using lldb functionality to free up any static resources +/// that have been allocated during initialization or during +/// function calls. No lldb functions should be called after +/// calling this function without again calling DCInitialize() +/// again. +//------------------------------------------------------------------ +void +Terminate(); + + +const char * +GetVersion (); + +const char * +GetVoteAsCString (Vote vote); + +const char * +GetSectionTypeAsCString (lldb::SectionType sect_type); + +bool +NameMatches (const char *name, NameMatchType match_type, const char *match); + +} // namespace lldb_private + + +#endif // defined(__cplusplus) + + +#endif // lldb_lldb_private_h_ diff --git a/include/lldb/lldb-public.h b/include/lldb/lldb-public.h new file mode 100644 index 0000000..b010edf --- /dev/null +++ b/include/lldb/lldb-public.h @@ -0,0 +1,18 @@ +//===-- lldb-include.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_lldb_h_ +#define LLDB_lldb_h_ + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#endif // LLDB_lldb_h_ diff --git a/include/lldb/lldb-python.h b/include/lldb/lldb-python.h new file mode 100644 index 0000000..229e396 --- /dev/null +++ b/include/lldb/lldb-python.h @@ -0,0 +1,29 @@ +//===-- lldb-python.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_lldb_python_h_ +#define LLDB_lldb_python_h_ + +// Python.h needs to be included before any system headers in order to avoid redefinition of macros + +#ifdef LLDB_DISABLE_PYTHON + +// Python is disabled in this build + +#else + +#if defined (__APPLE__) +#include <Python/Python.h> +#else +#include <Python.h> +#endif + +#endif // LLDB_DISABLE_PYTHON + +#endif // LLDB_lldb_python_h_ diff --git a/include/lldb/lldb-types.h b/include/lldb/lldb-types.h new file mode 100644 index 0000000..2693c0c --- /dev/null +++ b/include/lldb/lldb-types.h @@ -0,0 +1,83 @@ +//===-- lldb-types.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_lldb_types_h_ +#define LLDB_lldb_types_h_ + +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" + +#include <assert.h> +#include <pthread.h> +#include <signal.h> +#include <stdint.h> +#include <stdbool.h> +#include <unistd.h> + +//---------------------------------------------------------------------- +// All host systems must define: +// lldb::condition_t The native condition type (or a substitute class) for conditions on the host system. +// lldb::mutex_t The native mutex type for mutex objects on the host system. +// lldb::thread_t The native thread type for spawned threads on the system +// lldb::thread_arg_t The type of the one any only thread creation argument for the host system +// lldb::thread_result_t The return type that gets returned when a thread finishes. +// lldb::thread_func_t The function prototype used to spawn a thread on the host system. +// #define LLDB_INVALID_PROCESS_ID ... +// #define LLDB_INVALID_THREAD_ID ... +// #define LLDB_INVALID_HOST_THREAD ... +// #define IS_VALID_LLDB_HOST_THREAD ... +//---------------------------------------------------------------------- + +// TODO: Add a bunch of ifdefs to determine the host system and what +// things should be defined. Currently MacOSX is being assumed by default +// since that is what lldb was first developed for. + +namespace lldb { + //---------------------------------------------------------------------- + // MacOSX Types + //---------------------------------------------------------------------- + typedef ::pthread_mutex_t mutex_t; + typedef pthread_cond_t condition_t; + typedef pthread_t thread_t; // Host thread type + typedef void * thread_arg_t; // Host thread argument type + typedef void * thread_result_t; // Host thread result type + typedef void * (*thread_func_t)(void *); // Host thread function type + typedef void (*LogOutputCallback) (const char *, void *baton); + typedef bool (*CommandOverrideCallback)(void *baton, const char **argv); +} // namespace lldb + +#if defined(__MINGW32__) + +const lldb::thread_t lldb_invalid_host_thread_const = { NULL, 0 } ; +#define LLDB_INVALID_HOST_THREAD (lldb_invalid_host_thread_const) +#define IS_VALID_LLDB_HOST_THREAD(t) (!(NULL == (t).p && 0 == (t).x)) + +#else + +#define LLDB_INVALID_HOST_THREAD ((lldb::thread_t)NULL) +#define IS_VALID_LLDB_HOST_THREAD(t) ((t) != LLDB_INVALID_HOST_THREAD) + +#endif + +#define LLDB_INVALID_HOST_TIME { 0, 0 } + +namespace lldb +{ + typedef uint64_t addr_t; + typedef uint64_t user_id_t; + typedef uint64_t pid_t; + typedef uint64_t tid_t; + typedef uint64_t offset_t; + typedef int32_t break_id_t; + typedef int32_t watch_id_t; + typedef void * clang_type_t; +} + + +#endif // LLDB_lldb_types_h_ diff --git a/include/lldb/lldb-versioning.h b/include/lldb/lldb-versioning.h new file mode 100644 index 0000000..8ccc67d --- /dev/null +++ b/include/lldb/lldb-versioning.h @@ -0,0 +1,1607 @@ +//===-- lldb-versioning.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_lldb_versioning_h_ +#define LLDB_lldb_versioning_h_ + +//---------------------------------------------------------------------- +// LLDB API version +//---------------------------------------------------------------------- +#define LLDB_API_MAJOR_VERSION 1 +#define LLDB_API_MINOR_VERSION 0 + +/* + API versioning + --------------------------------- + + The LLDB API is versioned independently of the LLDB source base + Our API version numbers are composed of a major and a minor number + + The major number means a complete and stable revision of the API. Major numbers are compatibility breakers + (i.e. when we change the API major number, there is no promise of compatibility with the previous major version + and we are free to remove and/or change any APIs) + Minor numbers are a work-in-progress evolution of the API. APIs will not be removed or changed across minor versions + (minors do not break compatibility). However, we can deprecate APIs in minor versions or add new APIs in minor versions + A deprecated API is supposedly going to be removed in the next major version and will generate a warning if used + APIs we add in minor versions will not be removed (at least until the following major) but they might theoretically be deprecated + in a following minor version + Users are discouraged from using the LLDB version number to test for API features and should instead use the API version checking + as discussed below + + API version checking + --------------------------------- + + You can (optionally) sign into an API version checking feature + To do so you need to define three macros: + LLDB_API_CHECK_VERSIONING - define to any value (or no value) + LLDB_API_MAJOR_VERSION_WANTED - which major version of the LLDB API you are targeting + LLDB_API_MINOR_VERSION_WANTED - which minor version of the LLDB API you are targeting + + If these macros exist - LLDB will enable version checking of the public API + + If LLDB_API_MAJOR_VERSION is not equal to LLDB_API_MAJOR_VERSION_WANTED we will immediately halt your compilation with an error + This is by design, since we do not make any promise of compatibility across major versions - if you really want to test your luck, disable the versioning altogether + + If the major version test passes, you have signed up for a specific minor version of the API + Whenever we add or deprecate an API in a minor version, we will mark it with either + LLDB_API_NEW_IN_DOT_x - this API is new in LLDB .x + LLDB_API_DEPRECATED_IN_DOT_x - this API is deprecated as of .x + + If you are using an API new in DOT_x + if LLDB_API_MINOR_VERSION_WANTED >= x then all is well, else you will get a compilation error + This is meant to prevent you from using APIs that are newer than whatever LLDB you want to target + + If you are using an API deprecated in DOT_x + if LLDB_API_MINOR_VERSION_WANTED >= x then you will get a compilation warning, else all is well + This is meant to let you know that you are using an API that is deprecated and might go away + + Caveats + --------------------------------- + + Version checking only works on clang on OSX - you will get an error if you try to enable it on any other OS/compiler + If you want to enable version checking on other platforms, you will need to define appropriate implementations for + LLDB_API_IMPL_DEPRECATED and LLDB_API_IMPL_TOONEW and any other infrastructure your compiler needs for this purpose + + We have no deprecation-as-error mode + + There is no support for API versioning in Python + + We reserve to use macros whose names begin with LLDB_API_ and you should not use them in your source code as they might conflict + with present or future macro names we are using to implement versioning +*/ + +// if you want the version checking to work on other OS/compiler, define appropriate IMPL_DEPRECATED/IMPL_TOONEW +// and define LLDB_API_CHECK_VERSIONING_WORKS when you are ready to go live +#if defined(__APPLE__) && defined(__clang__) +#define LLDB_API_IMPL_DEPRECATED __attribute__((deprecated)) +#define LLDB_API_IMPL_TOONEW __attribute__((unavailable)) +#define LLDB_API_CHECK_VERSIONING_WORKS +#endif + +#if defined(LLDB_API_CHECK_VERSIONING) && !defined(LLDB_API_CHECK_VERSIONING_WORKS) +#error "API version checking will not work here - please disable or create and submit patches to lldb-versioning.h" +#endif + +#if defined(LLDB_API_CHECK_VERSIONING_WORKS) && (!defined(LLDB_API_IMPL_DEPRECATED) || !defined(LLDB_API_IMPL_TOONEW)) +#error "LLDB_API_CHECK_VERSIONING_WORKS needs LLDB_API_IMPL_DEPRECATED and LLDB_API_IMPL_TOONEW to be defined" +#endif + +#if defined(LLDB_API_CHECK_VERSIONING) && defined(LLDB_API_MAJOR_VERSION_WANTED) && defined(LLDB_API_MINOR_VERSION_WANTED) + +#if defined (LLDB_API_MAJOR_VERSION) && (LLDB_API_MAJOR_VERSION != LLDB_API_MAJOR_VERSION_WANTED) +#error "Cannot link using this LLDB version - public API versions are incompatible" +#endif + +#define LLDB_API_MINOR_VERSION_DOT_0 0 +#define LLDB_API_MINOR_VERSION_DOT_1 1 +#define LLDB_API_MINOR_VERSION_DOT_2 2 +#define LLDB_API_MINOR_VERSION_DOT_3 3 +#define LLDB_API_MINOR_VERSION_DOT_4 4 +#define LLDB_API_MINOR_VERSION_DOT_5 5 +#define LLDB_API_MINOR_VERSION_DOT_6 6 +#define LLDB_API_MINOR_VERSION_DOT_7 7 +#define LLDB_API_MINOR_VERSION_DOT_8 8 +#define LLDB_API_MINOR_VERSION_DOT_9 9 +#define LLDB_API_MINOR_VERSION_DOT_10 10 +#define LLDB_API_MINOR_VERSION_DOT_11 11 +#define LLDB_API_MINOR_VERSION_DOT_12 12 +#define LLDB_API_MINOR_VERSION_DOT_13 13 +#define LLDB_API_MINOR_VERSION_DOT_14 14 +#define LLDB_API_MINOR_VERSION_DOT_15 15 +#define LLDB_API_MINOR_VERSION_DOT_16 16 +#define LLDB_API_MINOR_VERSION_DOT_17 17 +#define LLDB_API_MINOR_VERSION_DOT_18 18 +#define LLDB_API_MINOR_VERSION_DOT_19 19 +#define LLDB_API_MINOR_VERSION_DOT_20 20 +#define LLDB_API_MINOR_VERSION_DOT_21 21 +#define LLDB_API_MINOR_VERSION_DOT_22 22 +#define LLDB_API_MINOR_VERSION_DOT_23 23 +#define LLDB_API_MINOR_VERSION_DOT_24 24 +#define LLDB_API_MINOR_VERSION_DOT_25 25 +#define LLDB_API_MINOR_VERSION_DOT_26 26 +#define LLDB_API_MINOR_VERSION_DOT_27 27 +#define LLDB_API_MINOR_VERSION_DOT_28 28 +#define LLDB_API_MINOR_VERSION_DOT_29 29 +#define LLDB_API_MINOR_VERSION_DOT_30 30 +#define LLDB_API_MINOR_VERSION_DOT_31 31 +#define LLDB_API_MINOR_VERSION_DOT_32 32 +#define LLDB_API_MINOR_VERSION_DOT_33 33 +#define LLDB_API_MINOR_VERSION_DOT_34 34 +#define LLDB_API_MINOR_VERSION_DOT_35 35 +#define LLDB_API_MINOR_VERSION_DOT_36 36 +#define LLDB_API_MINOR_VERSION_DOT_37 37 +#define LLDB_API_MINOR_VERSION_DOT_38 38 +#define LLDB_API_MINOR_VERSION_DOT_39 39 +#define LLDB_API_MINOR_VERSION_DOT_40 40 +#define LLDB_API_MINOR_VERSION_DOT_41 41 +#define LLDB_API_MINOR_VERSION_DOT_42 42 +#define LLDB_API_MINOR_VERSION_DOT_43 43 +#define LLDB_API_MINOR_VERSION_DOT_44 44 +#define LLDB_API_MINOR_VERSION_DOT_45 45 +#define LLDB_API_MINOR_VERSION_DOT_46 46 +#define LLDB_API_MINOR_VERSION_DOT_47 47 +#define LLDB_API_MINOR_VERSION_DOT_48 48 +#define LLDB_API_MINOR_VERSION_DOT_49 49 +#define LLDB_API_MINOR_VERSION_DOT_50 50 +#define LLDB_API_MINOR_VERSION_DOT_51 51 +#define LLDB_API_MINOR_VERSION_DOT_52 52 +#define LLDB_API_MINOR_VERSION_DOT_53 53 +#define LLDB_API_MINOR_VERSION_DOT_54 54 +#define LLDB_API_MINOR_VERSION_DOT_55 55 +#define LLDB_API_MINOR_VERSION_DOT_56 56 +#define LLDB_API_MINOR_VERSION_DOT_57 57 +#define LLDB_API_MINOR_VERSION_DOT_58 58 +#define LLDB_API_MINOR_VERSION_DOT_59 59 +#define LLDB_API_MINOR_VERSION_DOT_60 60 +#define LLDB_API_MINOR_VERSION_DOT_61 61 +#define LLDB_API_MINOR_VERSION_DOT_62 62 +#define LLDB_API_MINOR_VERSION_DOT_63 63 +#define LLDB_API_MINOR_VERSION_DOT_64 64 +#define LLDB_API_MINOR_VERSION_DOT_65 65 +#define LLDB_API_MINOR_VERSION_DOT_66 66 +#define LLDB_API_MINOR_VERSION_DOT_67 67 +#define LLDB_API_MINOR_VERSION_DOT_68 68 +#define LLDB_API_MINOR_VERSION_DOT_69 69 +#define LLDB_API_MINOR_VERSION_DOT_70 70 +#define LLDB_API_MINOR_VERSION_DOT_71 71 +#define LLDB_API_MINOR_VERSION_DOT_72 72 +#define LLDB_API_MINOR_VERSION_DOT_73 73 +#define LLDB_API_MINOR_VERSION_DOT_74 74 +#define LLDB_API_MINOR_VERSION_DOT_75 75 +#define LLDB_API_MINOR_VERSION_DOT_76 76 +#define LLDB_API_MINOR_VERSION_DOT_77 77 +#define LLDB_API_MINOR_VERSION_DOT_78 78 +#define LLDB_API_MINOR_VERSION_DOT_79 79 +#define LLDB_API_MINOR_VERSION_DOT_80 80 +#define LLDB_API_MINOR_VERSION_DOT_81 81 +#define LLDB_API_MINOR_VERSION_DOT_82 82 +#define LLDB_API_MINOR_VERSION_DOT_83 83 +#define LLDB_API_MINOR_VERSION_DOT_84 84 +#define LLDB_API_MINOR_VERSION_DOT_85 85 +#define LLDB_API_MINOR_VERSION_DOT_86 86 +#define LLDB_API_MINOR_VERSION_DOT_87 87 +#define LLDB_API_MINOR_VERSION_DOT_88 88 +#define LLDB_API_MINOR_VERSION_DOT_89 89 +#define LLDB_API_MINOR_VERSION_DOT_90 90 +#define LLDB_API_MINOR_VERSION_DOT_91 91 +#define LLDB_API_MINOR_VERSION_DOT_92 92 +#define LLDB_API_MINOR_VERSION_DOT_93 93 +#define LLDB_API_MINOR_VERSION_DOT_94 94 +#define LLDB_API_MINOR_VERSION_DOT_95 95 +#define LLDB_API_MINOR_VERSION_DOT_96 96 +#define LLDB_API_MINOR_VERSION_DOT_97 97 +#define LLDB_API_MINOR_VERSION_DOT_98 98 +#define LLDB_API_MINOR_VERSION_DOT_99 99 + +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_0 +#define LLDB_API_NEW_IN_DOT_0 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_0 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_0 +#define LLDB_API_DEPRECATED_IN_DOT_0 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_0 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_1 +#define LLDB_API_NEW_IN_DOT_1 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_1 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_1 +#define LLDB_API_DEPRECATED_IN_DOT_1 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_1 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_2 +#define LLDB_API_NEW_IN_DOT_2 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_2 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_2 +#define LLDB_API_DEPRECATED_IN_DOT_2 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_2 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_3 +#define LLDB_API_NEW_IN_DOT_3 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_3 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_3 +#define LLDB_API_DEPRECATED_IN_DOT_3 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_3 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_4 +#define LLDB_API_NEW_IN_DOT_4 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_4 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_4 +#define LLDB_API_DEPRECATED_IN_DOT_4 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_4 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_5 +#define LLDB_API_NEW_IN_DOT_5 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_5 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_5 +#define LLDB_API_DEPRECATED_IN_DOT_5 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_5 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_6 +#define LLDB_API_NEW_IN_DOT_6 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_6 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_6 +#define LLDB_API_DEPRECATED_IN_DOT_6 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_6 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_7 +#define LLDB_API_NEW_IN_DOT_7 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_7 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_7 +#define LLDB_API_DEPRECATED_IN_DOT_7 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_7 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_8 +#define LLDB_API_NEW_IN_DOT_8 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_8 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_8 +#define LLDB_API_DEPRECATED_IN_DOT_8 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_8 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_9 +#define LLDB_API_NEW_IN_DOT_9 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_9 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_9 +#define LLDB_API_DEPRECATED_IN_DOT_9 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_9 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_10 +#define LLDB_API_NEW_IN_DOT_10 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_10 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_10 +#define LLDB_API_DEPRECATED_IN_DOT_10 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_10 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_11 +#define LLDB_API_NEW_IN_DOT_11 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_11 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_11 +#define LLDB_API_DEPRECATED_IN_DOT_11 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_11 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_12 +#define LLDB_API_NEW_IN_DOT_12 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_12 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_12 +#define LLDB_API_DEPRECATED_IN_DOT_12 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_12 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_13 +#define LLDB_API_NEW_IN_DOT_13 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_13 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_13 +#define LLDB_API_DEPRECATED_IN_DOT_13 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_13 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_14 +#define LLDB_API_NEW_IN_DOT_14 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_14 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_14 +#define LLDB_API_DEPRECATED_IN_DOT_14 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_14 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_15 +#define LLDB_API_NEW_IN_DOT_15 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_15 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_15 +#define LLDB_API_DEPRECATED_IN_DOT_15 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_15 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_16 +#define LLDB_API_NEW_IN_DOT_16 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_16 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_16 +#define LLDB_API_DEPRECATED_IN_DOT_16 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_16 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_17 +#define LLDB_API_NEW_IN_DOT_17 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_17 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_17 +#define LLDB_API_DEPRECATED_IN_DOT_17 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_17 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_18 +#define LLDB_API_NEW_IN_DOT_18 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_18 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_18 +#define LLDB_API_DEPRECATED_IN_DOT_18 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_18 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_19 +#define LLDB_API_NEW_IN_DOT_19 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_19 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_19 +#define LLDB_API_DEPRECATED_IN_DOT_19 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_19 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_20 +#define LLDB_API_NEW_IN_DOT_20 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_20 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_20 +#define LLDB_API_DEPRECATED_IN_DOT_20 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_20 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_21 +#define LLDB_API_NEW_IN_DOT_21 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_21 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_21 +#define LLDB_API_DEPRECATED_IN_DOT_21 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_21 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_22 +#define LLDB_API_NEW_IN_DOT_22 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_22 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_22 +#define LLDB_API_DEPRECATED_IN_DOT_22 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_22 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_23 +#define LLDB_API_NEW_IN_DOT_23 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_23 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_23 +#define LLDB_API_DEPRECATED_IN_DOT_23 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_23 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_24 +#define LLDB_API_NEW_IN_DOT_24 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_24 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_24 +#define LLDB_API_DEPRECATED_IN_DOT_24 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_24 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_25 +#define LLDB_API_NEW_IN_DOT_25 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_25 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_25 +#define LLDB_API_DEPRECATED_IN_DOT_25 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_25 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_26 +#define LLDB_API_NEW_IN_DOT_26 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_26 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_26 +#define LLDB_API_DEPRECATED_IN_DOT_26 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_26 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_27 +#define LLDB_API_NEW_IN_DOT_27 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_27 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_27 +#define LLDB_API_DEPRECATED_IN_DOT_27 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_27 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_28 +#define LLDB_API_NEW_IN_DOT_28 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_28 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_28 +#define LLDB_API_DEPRECATED_IN_DOT_28 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_28 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_29 +#define LLDB_API_NEW_IN_DOT_29 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_29 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_29 +#define LLDB_API_DEPRECATED_IN_DOT_29 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_29 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_30 +#define LLDB_API_NEW_IN_DOT_30 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_30 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_30 +#define LLDB_API_DEPRECATED_IN_DOT_30 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_30 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_31 +#define LLDB_API_NEW_IN_DOT_31 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_31 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_31 +#define LLDB_API_DEPRECATED_IN_DOT_31 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_31 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_32 +#define LLDB_API_NEW_IN_DOT_32 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_32 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_32 +#define LLDB_API_DEPRECATED_IN_DOT_32 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_32 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_33 +#define LLDB_API_NEW_IN_DOT_33 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_33 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_33 +#define LLDB_API_DEPRECATED_IN_DOT_33 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_33 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_34 +#define LLDB_API_NEW_IN_DOT_34 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_34 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_34 +#define LLDB_API_DEPRECATED_IN_DOT_34 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_34 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_35 +#define LLDB_API_NEW_IN_DOT_35 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_35 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_35 +#define LLDB_API_DEPRECATED_IN_DOT_35 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_35 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_36 +#define LLDB_API_NEW_IN_DOT_36 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_36 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_36 +#define LLDB_API_DEPRECATED_IN_DOT_36 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_36 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_37 +#define LLDB_API_NEW_IN_DOT_37 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_37 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_37 +#define LLDB_API_DEPRECATED_IN_DOT_37 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_37 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_38 +#define LLDB_API_NEW_IN_DOT_38 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_38 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_38 +#define LLDB_API_DEPRECATED_IN_DOT_38 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_38 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_39 +#define LLDB_API_NEW_IN_DOT_39 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_39 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_39 +#define LLDB_API_DEPRECATED_IN_DOT_39 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_39 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_40 +#define LLDB_API_NEW_IN_DOT_40 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_40 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_40 +#define LLDB_API_DEPRECATED_IN_DOT_40 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_40 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_41 +#define LLDB_API_NEW_IN_DOT_41 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_41 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_41 +#define LLDB_API_DEPRECATED_IN_DOT_41 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_41 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_42 +#define LLDB_API_NEW_IN_DOT_42 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_42 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_42 +#define LLDB_API_DEPRECATED_IN_DOT_42 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_42 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_43 +#define LLDB_API_NEW_IN_DOT_43 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_43 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_43 +#define LLDB_API_DEPRECATED_IN_DOT_43 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_43 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_44 +#define LLDB_API_NEW_IN_DOT_44 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_44 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_44 +#define LLDB_API_DEPRECATED_IN_DOT_44 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_44 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_45 +#define LLDB_API_NEW_IN_DOT_45 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_45 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_45 +#define LLDB_API_DEPRECATED_IN_DOT_45 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_45 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_46 +#define LLDB_API_NEW_IN_DOT_46 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_46 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_46 +#define LLDB_API_DEPRECATED_IN_DOT_46 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_46 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_47 +#define LLDB_API_NEW_IN_DOT_47 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_47 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_47 +#define LLDB_API_DEPRECATED_IN_DOT_47 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_47 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_48 +#define LLDB_API_NEW_IN_DOT_48 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_48 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_48 +#define LLDB_API_DEPRECATED_IN_DOT_48 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_48 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_49 +#define LLDB_API_NEW_IN_DOT_49 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_49 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_49 +#define LLDB_API_DEPRECATED_IN_DOT_49 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_49 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_50 +#define LLDB_API_NEW_IN_DOT_50 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_50 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_50 +#define LLDB_API_DEPRECATED_IN_DOT_50 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_50 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_51 +#define LLDB_API_NEW_IN_DOT_51 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_51 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_51 +#define LLDB_API_DEPRECATED_IN_DOT_51 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_51 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_52 +#define LLDB_API_NEW_IN_DOT_52 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_52 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_52 +#define LLDB_API_DEPRECATED_IN_DOT_52 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_52 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_53 +#define LLDB_API_NEW_IN_DOT_53 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_53 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_53 +#define LLDB_API_DEPRECATED_IN_DOT_53 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_53 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_54 +#define LLDB_API_NEW_IN_DOT_54 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_54 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_54 +#define LLDB_API_DEPRECATED_IN_DOT_54 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_54 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_55 +#define LLDB_API_NEW_IN_DOT_55 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_55 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_55 +#define LLDB_API_DEPRECATED_IN_DOT_55 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_55 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_56 +#define LLDB_API_NEW_IN_DOT_56 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_56 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_56 +#define LLDB_API_DEPRECATED_IN_DOT_56 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_56 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_57 +#define LLDB_API_NEW_IN_DOT_57 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_57 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_57 +#define LLDB_API_DEPRECATED_IN_DOT_57 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_57 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_58 +#define LLDB_API_NEW_IN_DOT_58 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_58 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_58 +#define LLDB_API_DEPRECATED_IN_DOT_58 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_58 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_59 +#define LLDB_API_NEW_IN_DOT_59 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_59 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_59 +#define LLDB_API_DEPRECATED_IN_DOT_59 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_59 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_60 +#define LLDB_API_NEW_IN_DOT_60 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_60 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_60 +#define LLDB_API_DEPRECATED_IN_DOT_60 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_60 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_61 +#define LLDB_API_NEW_IN_DOT_61 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_61 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_61 +#define LLDB_API_DEPRECATED_IN_DOT_61 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_61 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_62 +#define LLDB_API_NEW_IN_DOT_62 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_62 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_62 +#define LLDB_API_DEPRECATED_IN_DOT_62 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_62 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_63 +#define LLDB_API_NEW_IN_DOT_63 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_63 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_63 +#define LLDB_API_DEPRECATED_IN_DOT_63 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_63 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_64 +#define LLDB_API_NEW_IN_DOT_64 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_64 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_64 +#define LLDB_API_DEPRECATED_IN_DOT_64 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_64 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_65 +#define LLDB_API_NEW_IN_DOT_65 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_65 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_65 +#define LLDB_API_DEPRECATED_IN_DOT_65 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_65 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_66 +#define LLDB_API_NEW_IN_DOT_66 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_66 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_66 +#define LLDB_API_DEPRECATED_IN_DOT_66 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_66 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_67 +#define LLDB_API_NEW_IN_DOT_67 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_67 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_67 +#define LLDB_API_DEPRECATED_IN_DOT_67 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_67 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_68 +#define LLDB_API_NEW_IN_DOT_68 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_68 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_68 +#define LLDB_API_DEPRECATED_IN_DOT_68 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_68 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_69 +#define LLDB_API_NEW_IN_DOT_69 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_69 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_69 +#define LLDB_API_DEPRECATED_IN_DOT_69 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_69 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_70 +#define LLDB_API_NEW_IN_DOT_70 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_70 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_70 +#define LLDB_API_DEPRECATED_IN_DOT_70 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_70 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_71 +#define LLDB_API_NEW_IN_DOT_71 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_71 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_71 +#define LLDB_API_DEPRECATED_IN_DOT_71 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_71 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_72 +#define LLDB_API_NEW_IN_DOT_72 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_72 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_72 +#define LLDB_API_DEPRECATED_IN_DOT_72 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_72 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_73 +#define LLDB_API_NEW_IN_DOT_73 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_73 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_73 +#define LLDB_API_DEPRECATED_IN_DOT_73 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_73 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_74 +#define LLDB_API_NEW_IN_DOT_74 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_74 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_74 +#define LLDB_API_DEPRECATED_IN_DOT_74 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_74 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_75 +#define LLDB_API_NEW_IN_DOT_75 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_75 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_75 +#define LLDB_API_DEPRECATED_IN_DOT_75 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_75 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_76 +#define LLDB_API_NEW_IN_DOT_76 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_76 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_76 +#define LLDB_API_DEPRECATED_IN_DOT_76 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_76 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_77 +#define LLDB_API_NEW_IN_DOT_77 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_77 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_77 +#define LLDB_API_DEPRECATED_IN_DOT_77 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_77 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_78 +#define LLDB_API_NEW_IN_DOT_78 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_78 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_78 +#define LLDB_API_DEPRECATED_IN_DOT_78 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_78 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_79 +#define LLDB_API_NEW_IN_DOT_79 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_79 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_79 +#define LLDB_API_DEPRECATED_IN_DOT_79 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_79 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_80 +#define LLDB_API_NEW_IN_DOT_80 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_80 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_80 +#define LLDB_API_DEPRECATED_IN_DOT_80 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_80 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_81 +#define LLDB_API_NEW_IN_DOT_81 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_81 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_81 +#define LLDB_API_DEPRECATED_IN_DOT_81 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_81 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_82 +#define LLDB_API_NEW_IN_DOT_82 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_82 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_82 +#define LLDB_API_DEPRECATED_IN_DOT_82 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_82 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_83 +#define LLDB_API_NEW_IN_DOT_83 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_83 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_83 +#define LLDB_API_DEPRECATED_IN_DOT_83 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_83 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_84 +#define LLDB_API_NEW_IN_DOT_84 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_84 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_84 +#define LLDB_API_DEPRECATED_IN_DOT_84 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_84 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_85 +#define LLDB_API_NEW_IN_DOT_85 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_85 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_85 +#define LLDB_API_DEPRECATED_IN_DOT_85 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_85 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_86 +#define LLDB_API_NEW_IN_DOT_86 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_86 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_86 +#define LLDB_API_DEPRECATED_IN_DOT_86 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_86 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_87 +#define LLDB_API_NEW_IN_DOT_87 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_87 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_87 +#define LLDB_API_DEPRECATED_IN_DOT_87 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_87 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_88 +#define LLDB_API_NEW_IN_DOT_88 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_88 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_88 +#define LLDB_API_DEPRECATED_IN_DOT_88 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_88 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_89 +#define LLDB_API_NEW_IN_DOT_89 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_89 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_89 +#define LLDB_API_DEPRECATED_IN_DOT_89 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_89 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_90 +#define LLDB_API_NEW_IN_DOT_90 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_90 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_90 +#define LLDB_API_DEPRECATED_IN_DOT_90 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_90 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_91 +#define LLDB_API_NEW_IN_DOT_91 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_91 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_91 +#define LLDB_API_DEPRECATED_IN_DOT_91 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_91 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_92 +#define LLDB_API_NEW_IN_DOT_92 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_92 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_92 +#define LLDB_API_DEPRECATED_IN_DOT_92 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_92 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_93 +#define LLDB_API_NEW_IN_DOT_93 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_93 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_93 +#define LLDB_API_DEPRECATED_IN_DOT_93 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_93 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_94 +#define LLDB_API_NEW_IN_DOT_94 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_94 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_94 +#define LLDB_API_DEPRECATED_IN_DOT_94 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_94 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_95 +#define LLDB_API_NEW_IN_DOT_95 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_95 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_95 +#define LLDB_API_DEPRECATED_IN_DOT_95 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_95 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_96 +#define LLDB_API_NEW_IN_DOT_96 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_96 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_96 +#define LLDB_API_DEPRECATED_IN_DOT_96 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_96 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_97 +#define LLDB_API_NEW_IN_DOT_97 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_97 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_97 +#define LLDB_API_DEPRECATED_IN_DOT_97 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_97 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_98 +#define LLDB_API_NEW_IN_DOT_98 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_98 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_98 +#define LLDB_API_DEPRECATED_IN_DOT_98 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_98 +#endif +#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_99 +#define LLDB_API_NEW_IN_DOT_99 LLDB_API_IMPL_TOONEW +#else +#define LLDB_API_NEW_IN_DOT_99 +#endif + + +#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_99 +#define LLDB_API_DEPRECATED_IN_DOT_99 LLDB_API_IMPL_DEPRECATED +#else +#define LLDB_API_DEPRECATED_IN_DOT_99 +#endif + +#else // defined(LLDB_CHECK_API_VERSIONING) && defined(LLDB_API_MAJOR_VERSION_WANTED) && defined(LLDB_API_MINOR_VERSION_WANTED) && defined (LLDB_API_MAJOR_VERSION) + +#define LLDB_API_NEW_IN_DOT_0 +#define LLDB_API_DEPRECATED_IN_DOT_0 +#define LLDB_API_NEW_IN_DOT_1 +#define LLDB_API_DEPRECATED_IN_DOT_1 +#define LLDB_API_NEW_IN_DOT_2 +#define LLDB_API_DEPRECATED_IN_DOT_2 +#define LLDB_API_NEW_IN_DOT_3 +#define LLDB_API_DEPRECATED_IN_DOT_3 +#define LLDB_API_NEW_IN_DOT_4 +#define LLDB_API_DEPRECATED_IN_DOT_4 +#define LLDB_API_NEW_IN_DOT_5 +#define LLDB_API_DEPRECATED_IN_DOT_5 +#define LLDB_API_NEW_IN_DOT_6 +#define LLDB_API_DEPRECATED_IN_DOT_6 +#define LLDB_API_NEW_IN_DOT_7 +#define LLDB_API_DEPRECATED_IN_DOT_7 +#define LLDB_API_NEW_IN_DOT_8 +#define LLDB_API_DEPRECATED_IN_DOT_8 +#define LLDB_API_NEW_IN_DOT_9 +#define LLDB_API_DEPRECATED_IN_DOT_9 +#define LLDB_API_NEW_IN_DOT_10 +#define LLDB_API_DEPRECATED_IN_DOT_10 +#define LLDB_API_NEW_IN_DOT_11 +#define LLDB_API_DEPRECATED_IN_DOT_11 +#define LLDB_API_NEW_IN_DOT_12 +#define LLDB_API_DEPRECATED_IN_DOT_12 +#define LLDB_API_NEW_IN_DOT_13 +#define LLDB_API_DEPRECATED_IN_DOT_13 +#define LLDB_API_NEW_IN_DOT_14 +#define LLDB_API_DEPRECATED_IN_DOT_14 +#define LLDB_API_NEW_IN_DOT_15 +#define LLDB_API_DEPRECATED_IN_DOT_15 +#define LLDB_API_NEW_IN_DOT_16 +#define LLDB_API_DEPRECATED_IN_DOT_16 +#define LLDB_API_NEW_IN_DOT_17 +#define LLDB_API_DEPRECATED_IN_DOT_17 +#define LLDB_API_NEW_IN_DOT_18 +#define LLDB_API_DEPRECATED_IN_DOT_18 +#define LLDB_API_NEW_IN_DOT_19 +#define LLDB_API_DEPRECATED_IN_DOT_19 +#define LLDB_API_NEW_IN_DOT_20 +#define LLDB_API_DEPRECATED_IN_DOT_20 +#define LLDB_API_NEW_IN_DOT_21 +#define LLDB_API_DEPRECATED_IN_DOT_21 +#define LLDB_API_NEW_IN_DOT_22 +#define LLDB_API_DEPRECATED_IN_DOT_22 +#define LLDB_API_NEW_IN_DOT_23 +#define LLDB_API_DEPRECATED_IN_DOT_23 +#define LLDB_API_NEW_IN_DOT_24 +#define LLDB_API_DEPRECATED_IN_DOT_24 +#define LLDB_API_NEW_IN_DOT_25 +#define LLDB_API_DEPRECATED_IN_DOT_25 +#define LLDB_API_NEW_IN_DOT_26 +#define LLDB_API_DEPRECATED_IN_DOT_26 +#define LLDB_API_NEW_IN_DOT_27 +#define LLDB_API_DEPRECATED_IN_DOT_27 +#define LLDB_API_NEW_IN_DOT_28 +#define LLDB_API_DEPRECATED_IN_DOT_28 +#define LLDB_API_NEW_IN_DOT_29 +#define LLDB_API_DEPRECATED_IN_DOT_29 +#define LLDB_API_NEW_IN_DOT_30 +#define LLDB_API_DEPRECATED_IN_DOT_30 +#define LLDB_API_NEW_IN_DOT_31 +#define LLDB_API_DEPRECATED_IN_DOT_31 +#define LLDB_API_NEW_IN_DOT_32 +#define LLDB_API_DEPRECATED_IN_DOT_32 +#define LLDB_API_NEW_IN_DOT_33 +#define LLDB_API_DEPRECATED_IN_DOT_33 +#define LLDB_API_NEW_IN_DOT_34 +#define LLDB_API_DEPRECATED_IN_DOT_34 +#define LLDB_API_NEW_IN_DOT_35 +#define LLDB_API_DEPRECATED_IN_DOT_35 +#define LLDB_API_NEW_IN_DOT_36 +#define LLDB_API_DEPRECATED_IN_DOT_36 +#define LLDB_API_NEW_IN_DOT_37 +#define LLDB_API_DEPRECATED_IN_DOT_37 +#define LLDB_API_NEW_IN_DOT_38 +#define LLDB_API_DEPRECATED_IN_DOT_38 +#define LLDB_API_NEW_IN_DOT_39 +#define LLDB_API_DEPRECATED_IN_DOT_39 +#define LLDB_API_NEW_IN_DOT_40 +#define LLDB_API_DEPRECATED_IN_DOT_40 +#define LLDB_API_NEW_IN_DOT_41 +#define LLDB_API_DEPRECATED_IN_DOT_41 +#define LLDB_API_NEW_IN_DOT_42 +#define LLDB_API_DEPRECATED_IN_DOT_42 +#define LLDB_API_NEW_IN_DOT_43 +#define LLDB_API_DEPRECATED_IN_DOT_43 +#define LLDB_API_NEW_IN_DOT_44 +#define LLDB_API_DEPRECATED_IN_DOT_44 +#define LLDB_API_NEW_IN_DOT_45 +#define LLDB_API_DEPRECATED_IN_DOT_45 +#define LLDB_API_NEW_IN_DOT_46 +#define LLDB_API_DEPRECATED_IN_DOT_46 +#define LLDB_API_NEW_IN_DOT_47 +#define LLDB_API_DEPRECATED_IN_DOT_47 +#define LLDB_API_NEW_IN_DOT_48 +#define LLDB_API_DEPRECATED_IN_DOT_48 +#define LLDB_API_NEW_IN_DOT_49 +#define LLDB_API_DEPRECATED_IN_DOT_49 +#define LLDB_API_NEW_IN_DOT_50 +#define LLDB_API_DEPRECATED_IN_DOT_50 +#define LLDB_API_NEW_IN_DOT_51 +#define LLDB_API_DEPRECATED_IN_DOT_51 +#define LLDB_API_NEW_IN_DOT_52 +#define LLDB_API_DEPRECATED_IN_DOT_52 +#define LLDB_API_NEW_IN_DOT_53 +#define LLDB_API_DEPRECATED_IN_DOT_53 +#define LLDB_API_NEW_IN_DOT_54 +#define LLDB_API_DEPRECATED_IN_DOT_54 +#define LLDB_API_NEW_IN_DOT_55 +#define LLDB_API_DEPRECATED_IN_DOT_55 +#define LLDB_API_NEW_IN_DOT_56 +#define LLDB_API_DEPRECATED_IN_DOT_56 +#define LLDB_API_NEW_IN_DOT_57 +#define LLDB_API_DEPRECATED_IN_DOT_57 +#define LLDB_API_NEW_IN_DOT_58 +#define LLDB_API_DEPRECATED_IN_DOT_58 +#define LLDB_API_NEW_IN_DOT_59 +#define LLDB_API_DEPRECATED_IN_DOT_59 +#define LLDB_API_NEW_IN_DOT_60 +#define LLDB_API_DEPRECATED_IN_DOT_60 +#define LLDB_API_NEW_IN_DOT_61 +#define LLDB_API_DEPRECATED_IN_DOT_61 +#define LLDB_API_NEW_IN_DOT_62 +#define LLDB_API_DEPRECATED_IN_DOT_62 +#define LLDB_API_NEW_IN_DOT_63 +#define LLDB_API_DEPRECATED_IN_DOT_63 +#define LLDB_API_NEW_IN_DOT_64 +#define LLDB_API_DEPRECATED_IN_DOT_64 +#define LLDB_API_NEW_IN_DOT_65 +#define LLDB_API_DEPRECATED_IN_DOT_65 +#define LLDB_API_NEW_IN_DOT_66 +#define LLDB_API_DEPRECATED_IN_DOT_66 +#define LLDB_API_NEW_IN_DOT_67 +#define LLDB_API_DEPRECATED_IN_DOT_67 +#define LLDB_API_NEW_IN_DOT_68 +#define LLDB_API_DEPRECATED_IN_DOT_68 +#define LLDB_API_NEW_IN_DOT_69 +#define LLDB_API_DEPRECATED_IN_DOT_69 +#define LLDB_API_NEW_IN_DOT_70 +#define LLDB_API_DEPRECATED_IN_DOT_70 +#define LLDB_API_NEW_IN_DOT_71 +#define LLDB_API_DEPRECATED_IN_DOT_71 +#define LLDB_API_NEW_IN_DOT_72 +#define LLDB_API_DEPRECATED_IN_DOT_72 +#define LLDB_API_NEW_IN_DOT_73 +#define LLDB_API_DEPRECATED_IN_DOT_73 +#define LLDB_API_NEW_IN_DOT_74 +#define LLDB_API_DEPRECATED_IN_DOT_74 +#define LLDB_API_NEW_IN_DOT_75 +#define LLDB_API_DEPRECATED_IN_DOT_75 +#define LLDB_API_NEW_IN_DOT_76 +#define LLDB_API_DEPRECATED_IN_DOT_76 +#define LLDB_API_NEW_IN_DOT_77 +#define LLDB_API_DEPRECATED_IN_DOT_77 +#define LLDB_API_NEW_IN_DOT_78 +#define LLDB_API_DEPRECATED_IN_DOT_78 +#define LLDB_API_NEW_IN_DOT_79 +#define LLDB_API_DEPRECATED_IN_DOT_79 +#define LLDB_API_NEW_IN_DOT_80 +#define LLDB_API_DEPRECATED_IN_DOT_80 +#define LLDB_API_NEW_IN_DOT_81 +#define LLDB_API_DEPRECATED_IN_DOT_81 +#define LLDB_API_NEW_IN_DOT_82 +#define LLDB_API_DEPRECATED_IN_DOT_82 +#define LLDB_API_NEW_IN_DOT_83 +#define LLDB_API_DEPRECATED_IN_DOT_83 +#define LLDB_API_NEW_IN_DOT_84 +#define LLDB_API_DEPRECATED_IN_DOT_84 +#define LLDB_API_NEW_IN_DOT_85 +#define LLDB_API_DEPRECATED_IN_DOT_85 +#define LLDB_API_NEW_IN_DOT_86 +#define LLDB_API_DEPRECATED_IN_DOT_86 +#define LLDB_API_NEW_IN_DOT_87 +#define LLDB_API_DEPRECATED_IN_DOT_87 +#define LLDB_API_NEW_IN_DOT_88 +#define LLDB_API_DEPRECATED_IN_DOT_88 +#define LLDB_API_NEW_IN_DOT_89 +#define LLDB_API_DEPRECATED_IN_DOT_89 +#define LLDB_API_NEW_IN_DOT_90 +#define LLDB_API_DEPRECATED_IN_DOT_90 +#define LLDB_API_NEW_IN_DOT_91 +#define LLDB_API_DEPRECATED_IN_DOT_91 +#define LLDB_API_NEW_IN_DOT_92 +#define LLDB_API_DEPRECATED_IN_DOT_92 +#define LLDB_API_NEW_IN_DOT_93 +#define LLDB_API_DEPRECATED_IN_DOT_93 +#define LLDB_API_NEW_IN_DOT_94 +#define LLDB_API_DEPRECATED_IN_DOT_94 +#define LLDB_API_NEW_IN_DOT_95 +#define LLDB_API_DEPRECATED_IN_DOT_95 +#define LLDB_API_NEW_IN_DOT_96 +#define LLDB_API_DEPRECATED_IN_DOT_96 +#define LLDB_API_NEW_IN_DOT_97 +#define LLDB_API_DEPRECATED_IN_DOT_97 +#define LLDB_API_NEW_IN_DOT_98 +#define LLDB_API_DEPRECATED_IN_DOT_98 +#define LLDB_API_NEW_IN_DOT_99 +#define LLDB_API_DEPRECATED_IN_DOT_99 +#endif // defined(LLDB_CHECK_API_VERSIONING) && defined(LLDB_API_MAJOR_VERSION_WANTED) && defined(LLDB_API_MINOR_VERSION_WANTED) && defined (LLDB_API_MAJOR_VERSION) + +#endif // LLDB_lldb_versioning_h_
\ No newline at end of file |